Participants

Great! At this point, I’ve run a Matlab script on the children’s raw data to collect XY gaze data for each video/trial they viewed. We start with 68 children. Here they are.

# Libraries
library(tidyverse)
library(feather)
library(lme4)
library(grid)
library(png)
library(lmerTest)
package ‘lmerTest’ was built under R version 3.4.3
#library(cowplot)
# Import data (and fix one participant name, and fix Owen as EnglishExposed)
data <- read_feather("../Child Data/childxydata.feather")
# Get ages
ages <- read_csv("childrenages.csv")
data <- data %>% left_join(ages, by = "participant")
data %>% select(participant,language,age) %>% distinct() # print data table

Removing Excluded Kids

I excluded all kids that were not included in the AOI analysis. Here is a list of all of ’em!

# Load included babies and children lists
included_babies <- read_feather("cleanedbabyeyedata.feather") %>%
  select(participant) %>% 
  distinct()
included_children <- read_feather("cleanedchildeyedata.feather") %>%
  select(participant) %>%
  distinct()
included <- rbind(included_babies, included_children)
# Use antijoin to see excluded kids
excluded <- anti_join(data, included, by = "participant") %>% 
  select(participant, language, age) %>% 
  distinct()
# Print table
excluded
# Remove excluded kids from main dataset
data <- semi_join(data, included, by = "participant")

Participant Tables and Charts

Let’s see a histogram of ages! After this I’ll add “baby” and “child” variables so all < 2.0 are identified as babies.

# Histogram of ages
data %>% select(participant,language,age) %>% 
  distinct() %>% 
  ggplot(aes(x = age)) + geom_histogram(fill = "royalblue", binwidth = 0.25) + ggtitle("Ages in Full Dataset")

# Add baby/child agegroup column
data <- data %>% 
  mutate(agegroup = age < 2.0) 
data$agegroup <- as.factor(data$agegroup)
data$agegroup <- fct_recode(data$agegroup, baby = "TRUE", child = "FALSE")

And our participant table.

participants_b <- data %>%
  filter(agegroup=="baby") %>%
  select(participant, gender, language, age) %>%
  distinct()
participants_b_n <- participants_b %>%
  count(gender, language) %>%
  spread(gender, n)
participants_b_age <- participants_b %>%
  group_by(language) %>%
  summarise(age_m = round(mean(age), 1), 
            age_sd = round(sd(age), 1),
            age_min = range(age)[1],
            age_max = range(age)[2]) %>%
  mutate(age_range = paste(age_min, age_max, sep = " - ")) %>%
  select(-age_min, -age_max) %>%
  mutate(age_mean = paste(age_m, age_sd, sep = "±")) %>%
  select(-age_m, -age_sd) %>%
  select(language, age_mean, age_range)
participants_table_b <- left_join(participants_b_n, participants_b_age, by = "language") %>%
  add_column(agegroup = "baby")
participants_c <- data %>%
  filter(agegroup=="child") %>%
  select(participant, gender, language, age) %>%
  distinct()
participants_c_n <- participants_c %>%
  count(gender, language) %>%
  spread(gender, n)
participants_c_age <- participants_c %>%
  group_by(language) %>%
  summarise(age_m = round(mean(age), 1), 
            age_sd = round(sd(age), 1),
            age_min = range(age)[1],
            age_max = range(age)[2]) %>%
  mutate(age_range = paste(age_min, age_max, sep = " - ")) %>%
  select(-age_min, -age_max) %>%
  mutate(age_mean = paste(age_m, age_sd, sep = "±")) %>%
  select(-age_m, -age_sd) %>%
  select(language, age_mean, age_range)
participants_table_c <- left_join(participants_c_n, participants_c_age, by = "language") %>%
  add_column(agegroup = "child")
rbind(participants_table_b, participants_table_c) %>% 
  select(language, agegroup, Female, Male, age_mean, age_range)

Save!

Great. Let’s save this as `cleanedchildxydata.csv’.

# Pull apart condition columns
data <- data %>%
  separate(condition, into = c("story", "clipnum", "direction", "media"), sep = "_") %>%
  unite(story, clipnum, col = "story", sep = "_") %>%
  select(-media) 
# A bit more cleaning up
data <- data %>%
  mutate(direction = case_when(
    direction == "FW" ~ "forward",
    direction == "ER" ~ "reversed"
  )) %>%
  mutate(language = case_when(
    language == "SignLanguageExposed" ~ "SE",
    language == "EnglishExposed" ~ "NSE"
  )) %>%
  mutate(group = as.factor(group),
         gender = as.factor(gender),
         language = as.factor(language),
         story = as.factor(story),
         direction = as.factor(direction))
# Save as csv and feather (feather preserves column types for R)
write_csv(data,"../Child Data/cleanedchildxydata.csv")
write_feather(data,"../Child Data/cleanedchildxydata.feather")

Any other data cleanup??

Do we need to do any other cleanup? I don’t think so.

Means vs Medians

First, let’s trim each participant’s data, getting rid of the first 60 samples (0.5 secs). Then we’ll get the the mean x and y coordinate for each story for each participant.

# Just to load data again 
data <- read_feather("../Child Data/cleanedchildxydata.feather")
data <- data %>%
  group_by(participant,trial) %>%
  slice(60:n())
data_central_tendencies <- data %>%
  group_by(language, agegroup, participant, trial) %>%
  summarise(mean_x = mean(x,na.rm=TRUE),
            mean_y = mean(y,na.rm=TRUE),
            median_x = median(x, na.rm=TRUE),
            median_y = median(y, na.rm=TRUE),
            diff_x = mean_x - median_x,
            diff_y = mean_y - median_y)
means <- data_central_tendencies %>%
  group_by(language, agegroup, participant) %>%
  summarise(mean_x = mean(mean_x, na.rm = TRUE),
            mean_y = mean(mean_y, na.rm = TRUE)) %>%
  group_by(language, agegroup) %>%
  summarise(sd_x = sd(mean_x),
            sd_y = sd(mean_y),
            n = n(),
            mean_x = mean(mean_x),
            mean_y = mean(mean_y)*-1,
            se_x = sd_x/sqrt(n),
            se_y = sd_y/sqrt(n))
means
means_error <- means %>%
  select(-n, -sd_x, -sd_y) %>%
  gather(measure, value, mean_x:se_y) %>%
  separate(measure, into = c("measure","axis")) %>%
  spread(measure, value)
means_error %>%
  filter(axis == "x") %>%
  ggplot(aes(x = agegroup, y = mean, color = language, group = language)) + 
  geom_point(position = position_dodge(width = 0.4)) +
  geom_errorbar(aes(ymin = mean-se, ymax = mean+se), 
                position = position_dodge(width = 0.4), width = 0.25, size = 0.5) + 
  scale_y_continuous(limits = c(0,1080)) +
  coord_flip() + 
  labs(y = "mean along x axis", title = "X-Axis Means")

means_error %>%
  filter(axis == "y") %>%
  ggplot(aes(x = agegroup, y = mean, color = language, group = language)) + 
  geom_point(position = position_dodge(width = 0.4)) +
  geom_errorbar(aes(ymin = mean-se, ymax = mean+se), 
                position = position_dodge(width = 0.4), width = 0.25, size = 0.5) + 
  scale_y_continuous(limits = c(-720,0)) +
  labs(y = "mean along y axis", title = "Y-Axis Means")

Distribution

But is the y-value distribution unimodal, bimodal, normal, what? Do the means represent the only peak? Let’s get histograms.

Maybe the mixture of stories and directions throws off the histograms. Let’s break it down by “mark” which is an unique number I assigned to each story/direction.

Still seems mostly unimodal (that means one peak, right?).

Skewness

But is the data skewed? I’ve been wondering if we should be using MEDIANS because there can be some extreme x and y values. But Rain said there’s been criticism of using medians and that means are better overall. Let’s have a look.

The first chart shows the difference between the mean and the median for each participant and trial. Positive means the mean is bigger than the median, negative means the median is bigger. It shows there is some skew for the y-axis…but the vast majority of differences is less than 50 px so maybe it’s okay.

The second chart shows the means and medians themselves. And the spread is pretty similar between mean and median so maybe using means is fine.

data_central_tendencies %>%
  gather(measure, value, diff_x:diff_y) %>%
  ggplot(aes(x = value)) + geom_histogram() + facet_grid(. ~ measure)

data_central_tendencies %>%
  gather(measure, value, mean_x:median_y) %>%
  separate(measure, into = c("measure","axis")) %>%
  ggplot(aes(x = value)) + geom_histogram() + facet_grid(measure ~ axis)

Testing the Means

Let’s run a LMM on the means. First, x means for babies.

means <- data %>%
  group_by(language, agegroup, participant, age, story, direction, trial, repetition) %>%
  summarise(x = mean(x, na.rm = TRUE),
            y = mean(y, na.rm = TRUE))
means$repetition = as.factor(means$repetition)
means$trial = as.factor(means$trial)
lmm_baby_mean_x <- lmer(x ~ language * direction + age + 
                          (1|story) + (1|participant) + (1|repetition) + (1|trial), 
                        data = filter(means, agegroup == "baby"))
summary(lmm_baby_mean_x)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: x ~ language * direction + age + (1 | story) + (1 | participant) +  
    (1 | repetition) + (1 | trial)
   Data: filter(means, agegroup == "baby")

REML criterion at convergence: 3239.3

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.3904 -0.4957  0.0510  0.4975  3.3887 

Random effects:
 Groups      Name        Variance  Std.Dev. 
 participant (Intercept) 8.647e+02 2.941e+01
 trial       (Intercept) 2.209e+01 4.700e+00
 story       (Intercept) 6.173e+01 7.857e+00
 repetition  (Intercept) 1.877e-13 4.333e-07
 Residual                7.927e+02 2.816e+01
Number of obs: 336, groups:  participant, 22; trial, 16; story, 8; repetition, 2

Fixed effects:
                             Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)                  535.1205    20.6764  20.2000  25.881   <2e-16 ***
languageSE                    -9.1352    15.5497  21.0400  -0.587    0.563    
directionreversed              2.2633     4.0361  62.9800   0.561    0.577    
age                           -3.2071    27.4906  19.0400  -0.117    0.908    
languageSE:directionreversed   0.1286     6.8950 295.0900   0.019    0.985    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) lnggSE drctnr age   
languageSE   0.075                     
dirctnrvrsd -0.092  0.103              
age         -0.914 -0.287 -0.003       
lnggSE:drct  0.045 -0.221 -0.481  0.000

Y means for babies

lmm_baby_mean_y <- lmer(y ~ language * direction + age + 
                          (1|story) + (1|participant) + (1|repetition) + (1|trial), 
                        data = filter(means, agegroup == "baby"))
summary(lmm_baby_mean_y)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: y ~ language * direction + age + (1 | story) + (1 | participant) +  
    (1 | repetition) + (1 | trial)
   Data: filter(means, agegroup == "baby")

REML criterion at convergence: 3506.1

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.6822 -0.5071 -0.0906  0.4159  7.4086 

Random effects:
 Groups      Name        Variance Std.Dev.
 participant (Intercept)  897.75  29.962  
 trial       (Intercept)    0.00   0.000  
 story       (Intercept)  137.43  11.723  
 repetition  (Intercept)   25.42   5.041  
 Residual                1880.38  43.363  
Number of obs: 336, groups:  participant, 22; trial, 16; story, 8; repetition, 2

Fixed effects:
                             Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)                   350.337     22.336  21.430  15.685 3.18e-13 ***
languageSE                    -25.177     16.854  23.270  -1.494    0.149    
directionreversed              -5.409      5.636 308.220  -0.960    0.338    
age                           -14.918     29.005  18.910  -0.514    0.613    
languageSE:directionreversed   -0.106     10.616 305.340  -0.010    0.992    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) lnggSE drctnr age   
languageSE   0.060                     
dirctnrvrsd -0.117  0.162              
age         -0.893 -0.280 -0.005       
lnggSE:drct  0.064 -0.314 -0.531  0.001

X means for children

lmm_child_mean_x <- lmer(x ~ language * direction + age + 
                          (1|story) + (1|participant) + (1|repetition) + (1|trial), 
                        data = filter(means, agegroup == "child"))
summary(lmm_child_mean_x)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: x ~ language * direction + age + (1 | story) + (1 | participant) +  
    (1 | repetition) + (1 | trial)
   Data: filter(means, agegroup == "child")

REML criterion at convergence: 4274.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-6.4290 -0.4704 -0.0121  0.4661  4.1860 

Random effects:
 Groups      Name        Variance Std.Dev.
 participant (Intercept) 242.043  15.558  
 trial       (Intercept)   0.000   0.000  
 story       (Intercept)  34.018   5.832  
 repetition  (Intercept)   5.778   2.404  
 Residual                551.029  23.474  
Number of obs: 462, groups:  participant, 30; trial, 16; story, 8; repetition, 2

Fixed effects:
                              Estimate Std. Error        df t value Pr(>|t|)    
(Intercept)                  514.35059   12.48227  29.70000  41.206   <2e-16 ***
languageSE                     3.60560    6.50348  34.80000   0.554    0.583    
directionreversed              0.07379    3.22374 427.50000   0.023    0.982    
age                            1.99964    2.26619  26.80000   0.882    0.385    
languageSE:directionreversed   1.76533    4.50536 429.50000   0.392    0.695    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) lnggSE drctnr age   
languageSE  -0.207                     
dirctnrvrsd -0.128  0.254              
age         -0.905 -0.060 -0.002       
lnggSE:drct  0.090 -0.347 -0.725  0.005

Y means for children

lmm_child_mean_y <- lmer(y ~ language * direction + age + 
                          (1|story) + (1|participant) + (1|repetition) + (1|trial), 
                        data = filter(means, agegroup == "child"))
summary(lmm_child_mean_y)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: y ~ language * direction + age + (1 | story) + (1 | participant) +  
    (1 | repetition) + (1 | trial)
   Data: filter(means, agegroup == "child")

REML criterion at convergence: 4972.8

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-4.9513 -0.4005 -0.0926  0.2908  5.6715 

Random effects:
 Groups      Name        Variance Std.Dev.
 participant (Intercept)  790.91  28.123  
 trial       (Intercept)    0.00   0.000  
 story       (Intercept)  186.46  13.655  
 repetition  (Intercept)   69.01   8.308  
 Residual                2578.64  50.780  
Number of obs: 462, groups:  participant, 30; trial, 16; story, 8; repetition, 2

Fixed effects:
                             Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)                  302.4237    23.9463  29.2000  12.629 2.31e-13 ***
languageSE                   -16.5870    12.3379  37.6000  -1.344    0.187    
directionreversed              6.2722     6.9835 428.5000   0.898    0.370    
age                            0.9306     4.2077  26.7000   0.221    0.827    
languageSE:directionreversed   1.3769     9.7551 429.5000   0.141    0.888    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) lnggSE drctnr age   
languageSE  -0.206                     
dirctnrvrsd -0.145  0.290              
age         -0.875 -0.060 -0.003       
lnggSE:drct  0.102 -0.396 -0.725  0.006

Let’s try it with both kids and babies.

lmm_all_mean_x <- lmer(x ~ language * direction * agegroup + 
                          (1|story) + (1|participant) + (1|repetition) + (1|trial), 
                        data = means)
summary(lmm_all_mean_x)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: x ~ language * direction * agegroup + (1 | story) + (1 | participant) +  
    (1 | repetition) + (1 | trial)
   Data: means

REML criterion at convergence: 7547.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-5.8393 -0.4558 -0.0024  0.4719  4.2147 

Random effects:
 Groups      Name        Variance Std.Dev.
 participant (Intercept) 480.143  21.912  
 trial       (Intercept)  13.005   3.606  
 story       (Intercept)  38.058   6.169  
 repetition  (Intercept)   4.629   2.152  
 Residual                658.194  25.655  
Number of obs: 798, groups:  participant, 52; trial, 16; story, 8; repetition, 2

Fixed effects:
                                          Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)                               523.9854     6.7976  48.1000  77.084   <2e-16 ***
languageSE                                  4.6003     8.6996  56.6000   0.529    0.599    
directionreversed                           0.7118     3.6930 250.9000   0.193    0.847    
agegroupbaby                                9.3634     8.5519  56.3000   1.095    0.278    
languageSE:directionreversed                0.5613     4.8729 730.5000   0.115    0.908    
languageSE:agegroupbaby                   -14.4961    14.3263  56.3000  -1.012    0.316    
directionreversed:agegroupbaby              0.7472     4.7488 726.5000   0.157    0.875    
languageSE:directionreversed:agegroupbaby  -0.1069     7.9089 725.2000  -0.014    0.989    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) lnggSE drctnr aggrpb lnggSE:d lnggSE:g drctn:
languageSE  -0.642                                              
dirctnrvrsd -0.274  0.191                                       
agegroupbby -0.652  0.509  0.189                                
lnggSE:drct  0.185 -0.280 -0.674 -0.145                         
lnggSE:ggrp  0.389 -0.607 -0.114 -0.597  0.169                  
drctnrvrsd:  0.185 -0.145 -0.673 -0.275  0.512    0.165         
lnggSE:drc: -0.112  0.171  0.407  0.166 -0.609   -0.276   -0.602
lmm_all_mean_y <- lmer(y ~ language * direction * agegroup + 
                          (1|story) + (1|participant) + (1|repetition) + (1|trial), 
                        data = means)
summary(lmm_all_mean_y)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: y ~ language * direction * agegroup + (1 | story) + (1 | participant) +  
    (1 | repetition) + (1 | trial)
   Data: means

REML criterion at convergence: 8494.8

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-5.2981 -0.4472 -0.1091  0.3394  6.6748 

Random effects:
 Groups      Name        Variance  Std.Dev. 
 participant (Intercept) 8.018e+02 2.832e+01
 trial       (Intercept) 4.055e-12 2.014e-06
 story       (Intercept) 1.611e+02 1.269e+01
 repetition  (Intercept) 5.352e+01 7.316e+00
 Residual                2.288e+03 4.783e+01
Number of obs: 798, groups:  participant, 52; trial, 16; story, 8; repetition, 2

Fixed effects:
                                          Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)                                307.421     10.996  14.100  27.957 9.48e-14 ***
languageSE                                 -16.943     12.142  64.400  -1.395  0.16770    
directionreversed                            5.573      6.470 742.000   0.861  0.38929    
agegroupbaby                                32.821     11.924  63.900   2.752  0.00769 ** 
languageSE:directionreversed                 2.174      9.085 740.900   0.239  0.81099    
languageSE:agegroupbaby                    -10.510     19.976  63.900  -0.526  0.60062    
directionreversed:agegroupbaby             -11.190      8.852 737.500  -1.264  0.20656    
languageSE:directionreversed:agegroupbaby   -2.598     14.743 736.100  -0.176  0.86019    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) lnggSE drctnr aggrpb lnggSE:d lnggSE:g drctn:
languageSE  -0.555                                              
dirctnrvrsd -0.297  0.271                                       
agegroupbby -0.563  0.511  0.270                                
lnggSE:drct  0.213 -0.374 -0.718 -0.193                         
lnggSE:ggrp  0.337 -0.607 -0.162 -0.597  0.225                  
drctnrvrsd:  0.213 -0.193 -0.715 -0.368  0.512    0.220         
lnggSE:drc: -0.129  0.228  0.434  0.222 -0.609   -0.369   -0.602

Summary

No difference in the mean looking position for x or y in children or babies! But if we put children and babies in the same dataset we get a significant main effect of children vs. babies. Okay.

Plotting One Kid

And I can get x or y plots of one participant across 8 stories. Let’s do Emmet. We’ll set the x and y limits to the whole width of the Tobii monitor (1600x1200…or is it now 1080x720). But because Tobii considers (0,0) to be the upper left corner (and not the bottom left corner), we also need to flip the y axis.

emmet <- filter(data,participant=="emmet_12_10_12_CODA") %>% mutate(y = y*-1)
ggplot(emmet,aes(x=x,y=y,color=story)) + geom_point(size=0.1) + geom_path() + facet_grid(repetition ~ story) + guides(color="none") + scale_x_continuous(limit=c(0,1080)) + scale_y_continuous(limit=c(-720,0))

Cool, yeah?

Viewing Space (SD)

To measure viewing space, we can use standard deviation or IQR. Generally, if we’re using means, we should use standard deviations. If we’re using medians, we should use IQR. That’s my thinking, anyway.

We’ll try SDs first. Let’s try the first SD, which is the middle 68% of the data.

sd <- data %>%
  group_by(participant, trial) %>%
  summarise(mean_x = mean(x, na.rm = TRUE),
            mean_y = mean(y, na.rm = TRUE),
            sd_x = sd(x, na.rm = TRUE),
            sd_y = sd(y, na.rm = TRUE)) %>%
  ungroup()
head(sd,10)
# join participant info back
participantinfo <- data %>%
  select(participant, trial, age, group, agegroup, gender, language, story, direction, mark, repetition) %>%
  distinct()
sd <- left_join(sd, participantinfo, by = c("participant","trial"))

And check out the histograms. I truncated the y-axis at 50 counts to better see outliers.

sd %>% 
  gather(axis,sd,sd_x:sd_y) %>%
  ggplot(aes(x=sd,fill=axis)) + geom_histogram() + facet_grid(axis~.) + 
  coord_cartesian(ylim = c(0,50))

So there are some really high outliers where the SD is 150 or 200 pixels in one direction (so a spread of as high as 400 pixels, which is a lot! I want to see those cases to see if they should be taken out or if we don’t need to worry about them.

It may be useful to think about getting rid of outliers. We should keep this in mind…

xoutliers <- sd %>%
  arrange(desc(sd_x)) %>%
  slice(1:20)
youtliers <- sd %>%
  arrange(desc(sd_y)) %>%
  slice(1:20)
xoutliers
youtliers

Testing

First, does reversal and language experience have an effect on the SD? Babies, x-axis first.

sd$trial <- as.factor(sd$trial)
sd$repetition <- as.factor(sd$repetition)
sd_x_baby <- lmer(sd_x ~ direction * language + age + (1|participant) + (1|story) + (1|repetition) + (1|trial), data = filter(sd, agegroup == "baby"))
summary(sd_x_baby)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: sd_x ~ direction * language + age + (1 | participant) + (1 |  
    story) + (1 | repetition) + (1 | trial)
   Data: filter(sd, agegroup == "baby")

REML criterion at convergence: 3199.1

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-1.9662 -0.5646 -0.1797  0.3836  5.7248 

Random effects:
 Groups      Name        Variance  Std.Dev. 
 participant (Intercept) 1.239e+02 1.113e+01
 trial       (Intercept) 4.300e-12 2.074e-06
 story       (Intercept) 2.114e+01 4.598e+00
 repetition  (Intercept) 0.000e+00 0.000e+00
 Residual                7.969e+02 2.823e+01
Number of obs: 336, groups:  participant, 22; trial, 16; story, 8; repetition, 2

Fixed effects:
                             Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)                    62.686      9.238  21.740   6.786 8.63e-07 ***
directionreversed              -1.777      3.655 311.990  -0.486    0.627    
languageSE                     -1.048      7.482  30.590  -0.140    0.890    
age                           -20.554     12.038  19.060  -1.707    0.104    
directionreversed:languageSE    6.175      6.902 307.500   0.895    0.372    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) drctnr lnggSE age   
dirctnrvrsd -0.185                     
languageSE   0.029  0.237              
age         -0.896 -0.007 -0.261       
drctnrvr:SE  0.100 -0.529 -0.461  0.001

That’s fine, we’re not exactly predicting changes along the x-axis. The y-axis is what we are really interested in! :)

sd_y_baby <- lmer(sd_y ~ direction * language + age + (1|participant) + (1|story) + (1|repetition) + (1|trial), data = filter(sd, agegroup == "baby"))
summary(sd_y_baby)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: sd_y ~ direction * language + age + (1 | participant) + (1 |  
    story) + (1 | repetition) + (1 | trial)
   Data: filter(sd, agegroup == "baby")

REML criterion at convergence: 3196.1

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.4863 -0.6696 -0.0402  0.5499  4.1535 

Random effects:
 Groups      Name        Variance  Std.Dev. 
 participant (Intercept) 1.971e+02 1.404e+01
 trial       (Intercept) 2.390e-13 4.889e-07
 story       (Intercept) 2.695e+01 5.191e+00
 repetition  (Intercept) 0.000e+00 0.000e+00
 Residual                7.703e+02 2.775e+01
Number of obs: 336, groups:  participant, 22; trial, 16; story, 8; repetition, 2

Fixed effects:
                             Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)                    86.272     10.877  21.070   7.932 9.23e-08 ***
directionreversed               1.546      3.597 310.980   0.430   0.6677    
languageSE                    -10.514      8.575  26.580  -1.226   0.2309    
age                           -30.506     14.279  18.960  -2.136   0.0459 *  
directionreversed:languageSE    8.096      6.789 306.990   1.193   0.2339    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) drctnr lnggSE age   
dirctnrvrsd -0.154                     
languageSE   0.045  0.204              
age         -0.903 -0.006 -0.270       
drctnrvr:SE  0.084 -0.530 -0.395  0.001

Now children, x-axis

sd_x_child <- lmer(sd_x ~ direction * language + age + (1|participant) + (1|story) + (1|repetition) + (1|trial), data = filter(sd, agegroup == "child"))
summary(sd_x_child)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: sd_x ~ direction * language + age + (1 | participant) + (1 |  
    story) + (1 | repetition) + (1 | trial)
   Data: filter(sd, agegroup == "child")

REML criterion at convergence: 4157.7

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-1.5828 -0.5697 -0.2273  0.2309  6.5944 

Random effects:
 Groups      Name        Variance  Std.Dev. 
 participant (Intercept) 3.374e+01 5.808e+00
 trial       (Intercept) 1.130e+01 3.362e+00
 story       (Intercept) 1.965e+00 1.402e+00
 repetition  (Intercept) 4.269e-13 6.533e-07
 Residual                4.737e+02 2.177e+01
Number of obs: 461, groups:  participant, 30; trial, 16; story, 8; repetition, 2

Fixed effects:
                             Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)                    37.923      6.093  31.200   6.224 6.29e-07 ***
directionreversed               5.170      3.153 121.400   1.640    0.104    
languageSE                     -2.885      3.586  57.900  -0.805    0.424    
age                            -1.203      1.090  26.200  -1.104    0.279    
directionreversed:languageSE   -1.466      4.102 376.100  -0.357    0.721    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) drctnr lnggSE age   
dirctnrvrsd -0.255                     
languageSE  -0.245  0.380              
age         -0.889 -0.005 -0.058       
drctnrvr:SE  0.163 -0.660 -0.572  0.010

And children, y-axis

sd_y_child <- lmer(sd_y ~ direction * language + age + (1|participant) + (1|story) + (1|repetition) + (1|trial), data = filter(sd, agegroup == "child"))
summary(sd_y_child)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: sd_y ~ direction * language + age + (1 | participant) + (1 |  
    story) + (1 | repetition) + (1 | trial)
   Data: filter(sd, agegroup == "child")

REML criterion at convergence: 4408.7

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.0653 -0.6574 -0.2026  0.4676  4.4651 

Random effects:
 Groups      Name        Variance Std.Dev.
 participant (Intercept) 195.21   13.972  
 trial       (Intercept)   0.00    0.000  
 story       (Intercept)  16.03    4.003  
 repetition  (Intercept)   0.00    0.000  
 Residual                787.89   28.069  
Number of obs: 461, groups:  participant, 30; trial, 16; story, 8; repetition, 2

Fixed effects:
                             Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)                    65.689     11.618  29.000   5.654 4.11e-06 ***
directionreversed               5.244      3.808 401.100   1.377   0.1693    
languageSE                    -11.615      6.336  39.800  -1.833   0.0743 .  
age                            -2.757      2.133  26.900  -1.292   0.2073    
directionreversed:languageSE   -2.820      5.341 421.500  -0.528   0.5978    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) drctnr lnggSE age   
dirctnrvrsd -0.162                     
languageSE  -0.219  0.305              
age         -0.914 -0.004 -0.060       
drctnrvr:SE  0.112 -0.719 -0.421  0.007

And now all babies/children, x axis

sd_x_all <- lmer(sd_x ~ direction * language * agegroup + (1|participant) + (1|story) + (1|repetition) + (1|trial), data = sd)
summary(sd_x_all)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: sd_x ~ direction * language * agegroup + (1 | participant) +  
    (1 | story) + (1 | repetition) + (1 | trial)
   Data: sd

REML criterion at convergence: 7398.8

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.1004 -0.5510 -0.1986  0.3067  6.6453 

Random effects:
 Groups      Name        Variance Std.Dev.
 participant (Intercept)  79.076   8.892  
 trial       (Intercept)  10.557   3.249  
 story       (Intercept)   8.751   2.958  
 repetition  (Intercept)   0.000   0.000  
 Residual                607.361  24.645  
Number of obs: 797, groups:  participant, 52; trial, 16; story, 8; repetition, 2

Fixed effects:
                                          Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)                                32.0056     3.5716  73.4000   8.961 2.12e-13 ***
directionreversed                           5.0971     3.5042 282.5000   1.455 0.146901    
languageSE                                 -3.3573     4.6084  86.2000  -0.729 0.468265    
agegroupbaby                               16.2198     4.5209  85.1000   3.588 0.000556 ***
directionreversed:languageSE               -1.0377     4.6582 729.0000  -0.223 0.823782    
directionreversed:agegroupbaby             -6.3725     4.5559 731.7000  -1.399 0.162315    
languageSE:agegroupbaby                    -0.9728     7.5755  85.2000  -0.128 0.898128    
directionreversed:languageSE:agegroupbaby   7.3354     7.5895 728.6000   0.967 0.334100    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) drctnr lnggSE aggrpb drc:SE drctn: lngSE:
dirctnrvrsd -0.492                                          
languageSE  -0.650  0.343                                   
agegroupbby -0.660  0.344  0.512                            
drctnrvr:SE  0.333 -0.676 -0.505 -0.260                     
drctnrvrsd:  0.334 -0.678 -0.260 -0.498  0.511              
lnggSE:ggrp  0.394 -0.207 -0.607 -0.597  0.305  0.298       
drctnrv:SE: -0.202  0.409  0.307  0.300 -0.609 -0.602 -0.500
sd_y_all <- lmer(sd_y*2 ~ direction * language * agegroup + (1|participant) + (1|story) + (1|repetition) + (1|trial), data = sd)
summary(sd_y_all)
Linear mixed model fit by REML t-tests use Satterthwaite approximations to degrees of freedom [lmerMod]
Formula: sd_y * 2 ~ direction * language * agegroup + (1 | participant) +  
    (1 | story) + (1 | repetition) + (1 | trial)
   Data: sd

REML criterion at convergence: 8718.1

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.4227 -0.6553 -0.1538  0.4938  4.5262 

Random effects:
 Groups      Name        Variance Std.Dev.
 participant (Intercept)  867.34  29.451  
 trial       (Intercept)    6.99   2.644  
 story       (Intercept)   41.39   6.433  
 repetition  (Intercept)    0.00   0.000  
 Residual                3154.01  56.161  
Number of obs: 797, groups:  participant, 52; trial, 16; story, 8; repetition, 2

Fixed effects:
                                          Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)                                103.710      9.579  68.400  10.827 2.22e-16 ***
directionreversed                           10.802      7.606 270.100   1.420   0.1567    
languageSE                                 -24.096     13.082  68.700  -1.842   0.0698 .  
agegroupbaby                                26.902     12.850  68.100   2.094   0.0400 *  
directionreversed:languageSE                -5.750     10.606 727.000  -0.542   0.5879    
directionreversed:agegroupbaby              -7.734     10.381 731.500  -0.745   0.4565    
languageSE:agegroupbaby                     -6.820     21.530  68.200  -0.317   0.7524    
directionreversed:languageSE:agegroupbaby   21.671     17.294 728.400   1.253   0.2106    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) drctnr lnggSE aggrpb drc:SE drctn: lngSE:
dirctnrvrsd -0.399                                          
languageSE  -0.686  0.289                                   
agegroupbby -0.697  0.289  0.510                            
drctnrvr:SE  0.283 -0.708 -0.405 -0.208                     
drctnrvrsd:  0.283 -0.709 -0.208 -0.399  0.510              
lnggSE:ggrp  0.416 -0.174 -0.607 -0.597  0.244  0.239       
drctnrv:SE: -0.171  0.428  0.246  0.240 -0.609 -0.601 -0.401

Summary

So there is no effect of language or direction (or interactions) on the standard deviation. Among babies, there seems to be an effect of age on y-axis viewing space such that it narrows the older the baby is (p = 0.046).

When we put babies and children together, we see age group differences for sd_x and sd_y, not surprisingly.

Everything after this needs to be updated.

Viewing Space (IQR)

Now let’s get the middle 50% (aka the IQR) of x and y for each participant’s story (we’ve already trimmed the first 60 samples). That should also take care of further weird outliers. And we are defining “viewing space” as the IQR of the x and y axis.

iqr <- data %>%
  group_by(participant,trial) %>%
  summarise(xIQR = IQR(x,na.rm=TRUE),
                   yIQR = IQR(y,na.rm=TRUE),
                   xmed = median(x, na.rm=TRUE),
                   ymed = median(y, na.rm=TRUE)) %>%
  ungroup()
head(iqr,10)
# Join participant info back into IQR table
participantinfo <- data %>%
  select(participant, trial, age, group, gender, language, story, direction, mark, repetition) %>%
  distinct()
iqr <- left_join(iqr, participantinfo, by = c("participant","trial"))

And check out the histograms. I truncated the y-axis at 100 to better see outliers.

iqr %>% 
  gather(axis,iqr,xIQR:yIQR) %>%
  ggplot(aes(x=iqr,fill=axis)) + geom_histogram() + facet_grid(axis~.) + 
  coord_cartesian(ylim = c(0,50))

So we see some outliers. Who are those? Let’s get a table of them. Review those AFTER I’ve done the cleanups of course.

xoutliers <- iqr %>%
  arrange(desc(xIQR)) %>%
  slice(1:10)
youtliers <- iqr %>%
  arrange(desc(yIQR)) %>%
  slice(1:10)

Next, check the medians.

iqr %>% 
  gather(axis,med,xmed:ymed) %>%
  ggplot(aes(x=med,fill=axis)) + geom_histogram() + facet_grid(axis~.) + 
  coord_cartesian(ylim = c(0,50))

SO I need to review those too. After cleaning up/removing kids.

iqr.gather <- iqr %>% gather(axis,value,xIQR:ymed)
iqr.iqr <- filter(iqr.gather,axis=="xIQR" | axis=="yIQR")
iqr.med <- filter(iqr.gather,axis=="xmed" | axis=="ymed")
ggplot(iqr.iqr,aes(x=language,y=value,fill=direction)) + 
  geom_boxplot() + theme(axis.text.x=element_text(angle=45,hjust=1)) +
  facet_grid(.~axis)

And the median x and y position (this assumes all calibrations are correct):

ggplot(iqr.med,aes(x=language,y=value,fill=direction)) + 
  geom_boxplot() + theme(axis.text.x=element_text(angle=45,hjust=1)) +
  facet_grid(.~axis)

First, does reversal and language experience have an effect on X IQR? We have random intercepts for each participant and media, and a random slope adjustment for reversed for each participant.

xiqr.reversal <- lmer(xIQR ~ direction * language + (direction|participant) + (1|story), data = iqr)
summary(xiqr.reversal)$coefficients
                              Estimate Std. Error        df   t value   Pr(>|t|)
(Intercept)                  38.708678   2.396168  47.13069 16.154407 0.00000000
directionreversed             3.358776   2.318054 621.22252  1.448964 0.14785227
languageSE                   -9.026396   3.726797  56.47549 -2.422025 0.01866818
directionreversed:languageSE -1.948012   3.634404 713.57954 -0.535992 0.59213108

That’s fine, we’re not exactly predicting changes along the x-axis. The y-axis is what we are really interested in! :)

yiqr.reversal <- lmer(yIQR ~ direction * language + (direction|participant) + (1|story), data = iqr)
summary(yiqr.reversal)$coefficients
                               Estimate Std. Error        df   t value    Pr(>|t|)
(Intercept)                   63.239876   4.933487  49.68294 12.818495 0.000000000
directionreversed              9.340253   4.692411 172.59784  1.990502 0.048114103
languageSE                   -21.646409   7.748662  55.75654 -2.793567 0.007131564
directionreversed:languageSE  -8.777486   7.367880 179.04123 -1.191318 0.235105783

Viewing Space Charts

I want to learn how to make rectangle plots so here we go. Using each participant’s four x and y medians and 4 x and y IQRs (one set for each story, for 4 stories). So I can get the logic and code down. Let’s assume all calibrations were correct. Here’s the chart for the whole media size of 1440x1080 (as reported in Tobii).

# In this order, we'll get a grand median by taking a participant's median across their 4 stories, than the median for forward and reverse across all participants. 
medians <- iqr %>%
  group_by(participant,direction) %>%
  summarise(xIQR = median(xIQR,na.rm=TRUE),
                   yIQR = median(yIQR,na.rm=TRUE),
                   xmed = median(xmed,na.rm=TRUE),
                   ymed = median(ymed,na.rm=TRUE)) %>%
  group_by(direction) %>% 
  summarise(xIQR = median(xIQR,na.rm=TRUE),
                   yIQR = median(yIQR,na.rm=TRUE),
                   x = median(xmed,na.rm=TRUE),
                   y = median(ymed,na.rm=TRUE))
medians <- medians %>%
  mutate(y = y*-1,
         xmin = x-(xIQR/2),
         xmax = x+(xIQR/2),
         ymin = y-(yIQR/2),
         ymax = y+(yIQR/2))
img <- readPNG("cindy.png")
g <- rasterGrob(img, interpolate=TRUE, width=unit(1,"npc"), height=unit(1,"npc")) 
ggplot(medians, aes(fill=direction,color=direction)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
  theme_minimal() + xlim(0,1440) + ylim(-1080,0)

# ggplot(iqr.global, aes(fill=direction,color=direction)) +
#   annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
#   geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
#   theme_minimal() + xlim(0,1440) + ylim(-1080,0) +
#   geom_hline(yintercept=-1080+885) +
#   geom_hline(yintercept=-1080+525) + 
#   annotate(geom="text", x = 300, y = -1080+555, label = "upper shoulder point") +
#   annotate(geom="point", x = 535, y = -1080+525) + 
#   annotate(geom="text", x = 535, y = -1080+910, label = "height line") + 
#   annotate(geom="rect", xmin = 535, xmax = 535+365, ymin = -525-551, ymax = -1080+525, fill="maroon", color="black", alpha=0.5) + 
#   annotate(geom="text", x = 700, y = -900, label = "torso")

Viewing Space Charts for Individuals

Now let’s see the variation in viewing spaces for all our individuals. Should be fun.

iqr.individuals <- iqr %>%
  rename(x = xmed,
         y = ymed) %>%
  mutate(y = y*-1,
         xmin = x-(xIQR/2),
         xmax = x+(xIQR/2),
         ymin = y-(yIQR/2),
         ymax = y+(yIQR/2))
ggplot(iqr.individuals, aes(fill=direction,color=direction)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
  theme_minimal() + xlim(0,1440) + ylim(-1080,0) + facet_wrap("direction") +
  ggtitle("with IQRs")

Now let’s make Outer Limits charts which is IQR +/- 2 SDs. But I want to change that because I don’t like the idea of mixing IQRs and SDs.

# sd.individuals <- select(sd.individuals,participant,media,xsd,ysd)
# iqrsd.individuals <- left_join(iqr.individuals,sd.individuals,by=c("participant","media")) %>%
#   mutate(xmin = xmin-(2*xsd),
#          xmax = xmax+(2*xsd),
#          ymin = ymin-(2*ysd),
#          ymax = ymax+(2*ysd))
# 
# ggplot(iqrsd.individuals, aes(fill=direction,color=direction)) +
#   annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
#   geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
#   theme_minimal() + xlim(0,1440) + ylim(-1080,0) + facet_wrap("direction") +
#   ggtitle("with SDs")
# iqrsd.individuals <- iqrsd.individuals %>%
#   group_by(direction) %>%
#   dplyr::summarize(x = mean(x,na.rm=TRUE),
#             y = mean(y,na.rm=TRUE),
#             xmin = mean(xmin,na.rm=TRUE),
#             ymin = mean(ymin,na.rm=TRUE),
#             xmax = mean(xmax,na.rm=TRUE),
#             ymax = mean(ymax,na.rm=TRUE))
# ggplot(iqrsd.individuals, aes(fill=direction,color=direction)) +
#   annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
#   geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
#   theme_minimal() + xlim(0,1440) + ylim(-1080,0) + facet_wrap("direction") +
#   ggtitle("Average of above chart (rain's outer limits)")

Within-Subject Variation

Just read this good post about plotting within-subject variation and saw it can really apply to this dataset. So I’m going to try out one example.

We know the y means aren’t significantly different across groups but that’s been hard to visualize on a per-subject basis (or even from an error bar chart since the error bars are so small). Let’s visualize that!

LS0tCnRpdGxlOiAiUmF3IFhZIERhdGEgKHN0dWR5MmNoaWxkcmVuKSIKYXV0aG9yOiAiQWRhbSBTdG9uZSwgUGhEIiAKZGF0ZTogJ2ByIGZvcm1hdChTeXMuRGF0ZSgpLCAiJW0tJWQtJVkiKWAnCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0aGVtZTogc3BhY2VsYWIKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDIKICAgIHRvY19mbG9hdDogeWVzCiAgICBkZl9wcmludDogcGFnZWQKLS0tCgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojIFRoaXMgaXMgdG8gZ2V0IGFsbCBraWRzJyBfcHJvY2Vzc2VkXyBYWSBkYXRhIGludG8gb25lIHNpbmdsZSBmaWxlLiBTaG91bGQgb25seSBydW4gd2hlbiBuZWVkZWQuIApsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShmZWF0aGVyKQoKY3N2cGF0aCA9ICIuLi9DaGlsZCBEYXRhL194eWRhdGEvIgpmaWxlcyA8LSBkaXIocGF0aCA9IGNzdnBhdGgsIHBhdHRlcm4gPSAiX3h5ZGF0YSIpCmZpbGVzIDwtIHBhc3RlKGNzdnBhdGgsIGZpbGVzLCBzZXA9IiIpCmRhdGEgPC0gZmlsZXMgJT4lCiAgbWFwKHJlYWRfY3N2KSAlPiUKICByZWR1Y2UocmJpbmQpICU+JQogIG11dGF0ZShwYXJ0aWNpcGFudCA9IGNhc2Vfd2hlbigKICAgIHBhcnRpY2lwYW50ID09ICJBYjA3b3YwOV8yMm0iIH4gIkFiMDdvdjA5XzMybSIsCiAgICBUUlVFIH4gcGFydGljaXBhbnQKICApKSAlPiUKICBtdXRhdGUobGFuZ3VhZ2UgPSBjYXNlX3doZW4oCiAgICBwYXJ0aWNpcGFudCA9PSAiT3dlblR3aW4wMzAyMTJfNHkybSIgfiAiRW5nbGlzaEV4cG9zZWQiLAogICAgVFJVRSB+IGxhbmd1YWdlCiAgKSkKd3JpdGVfZmVhdGhlcihkYXRhLCAiLi4vQ2hpbGQgRGF0YS9jaGlsZHh5ZGF0YS5mZWF0aGVyIikKYGBgCgojIFBhcnRpY2lwYW50cwoKR3JlYXQhIEF0IHRoaXMgcG9pbnQsIEkndmUgcnVuIGEgTWF0bGFiIHNjcmlwdCBvbiB0aGUgY2hpbGRyZW4ncyByYXcgZGF0YSB0byBjb2xsZWN0IFhZIGdhemUgZGF0YSBmb3IgZWFjaCB2aWRlby90cmlhbCB0aGV5IHZpZXdlZC4gV2Ugc3RhcnQgd2l0aCA2OCBjaGlsZHJlbi4gSGVyZSB0aGV5IGFyZS4gCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQojIExpYnJhcmllcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShmZWF0aGVyKQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkoZ3JpZCkKbGlicmFyeShwbmcpCmxpYnJhcnkobG1lclRlc3QpCiNsaWJyYXJ5KGNvd3Bsb3QpCgojIEltcG9ydCBkYXRhIChhbmQgZml4IG9uZSBwYXJ0aWNpcGFudCBuYW1lLCBhbmQgZml4IE93ZW4gYXMgRW5nbGlzaEV4cG9zZWQpCmRhdGEgPC0gcmVhZF9mZWF0aGVyKCIuLi9DaGlsZCBEYXRhL2NoaWxkeHlkYXRhLmZlYXRoZXIiKQoKIyBHZXQgYWdlcwphZ2VzIDwtIHJlYWRfY3N2KCJjaGlsZHJlbmFnZXMuY3N2IikKZGF0YSA8LSBkYXRhICU+JSBsZWZ0X2pvaW4oYWdlcywgYnkgPSAicGFydGljaXBhbnQiKQpkYXRhICU+JSBzZWxlY3QocGFydGljaXBhbnQsbGFuZ3VhZ2UsYWdlKSAlPiUgZGlzdGluY3QoKSAjIHByaW50IGRhdGEgdGFibGUKYGBgCgojIyBSZW1vdmluZyBFeGNsdWRlZCBLaWRzCgpJIGV4Y2x1ZGVkIGFsbCBraWRzIHRoYXQgd2VyZSBub3QgaW5jbHVkZWQgaW4gdGhlIEFPSSBhbmFseXNpcy4gSGVyZSBpcyBhIGxpc3Qgb2YgYWxsIG9mICdlbSEKCmBgYHtyIGVjaG89VFJVRX0KIyBMb2FkIGluY2x1ZGVkIGJhYmllcyBhbmQgY2hpbGRyZW4gbGlzdHMKaW5jbHVkZWRfYmFiaWVzIDwtIHJlYWRfZmVhdGhlcigiY2xlYW5lZGJhYnlleWVkYXRhLmZlYXRoZXIiKSAlPiUKICBzZWxlY3QocGFydGljaXBhbnQpICU+JSAKICBkaXN0aW5jdCgpCmluY2x1ZGVkX2NoaWxkcmVuIDwtIHJlYWRfZmVhdGhlcigiY2xlYW5lZGNoaWxkZXllZGF0YS5mZWF0aGVyIikgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50KSAlPiUKICBkaXN0aW5jdCgpCmluY2x1ZGVkIDwtIHJiaW5kKGluY2x1ZGVkX2JhYmllcywgaW5jbHVkZWRfY2hpbGRyZW4pCgojIFVzZSBhbnRpam9pbiB0byBzZWUgZXhjbHVkZWQga2lkcwpleGNsdWRlZCA8LSBhbnRpX2pvaW4oZGF0YSwgaW5jbHVkZWQsIGJ5ID0gInBhcnRpY2lwYW50IikgJT4lIAogIHNlbGVjdChwYXJ0aWNpcGFudCwgbGFuZ3VhZ2UsIGFnZSkgJT4lIAogIGRpc3RpbmN0KCkKCiMgUHJpbnQgdGFibGUKZXhjbHVkZWQKCiMgUmVtb3ZlIGV4Y2x1ZGVkIGtpZHMgZnJvbSBtYWluIGRhdGFzZXQKZGF0YSA8LSBzZW1pX2pvaW4oZGF0YSwgaW5jbHVkZWQsIGJ5ID0gInBhcnRpY2lwYW50IikKYGBgCgojIyBQYXJ0aWNpcGFudCBUYWJsZXMgYW5kIENoYXJ0cwoKTGV0J3Mgc2VlIGEgaGlzdG9ncmFtIG9mIGFnZXMhIEFmdGVyIHRoaXMgSSdsbCBhZGQgImJhYnkiIGFuZCAiY2hpbGQiIHZhcmlhYmxlcyBzbyBhbGwgPCAyLjAgYXJlIGlkZW50aWZpZWQgYXMgYmFiaWVzLiAKCmBgYHtyfQojIEhpc3RvZ3JhbSBvZiBhZ2VzCmRhdGEgJT4lIHNlbGVjdChwYXJ0aWNpcGFudCxsYW5ndWFnZSxhZ2UpICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhZ2UpKSArIGdlb21faGlzdG9ncmFtKGZpbGwgPSAicm95YWxibHVlIiwgYmlud2lkdGggPSAwLjI1KSArIGdndGl0bGUoIkFnZXMgaW4gRnVsbCBEYXRhc2V0IikKCiMgQWRkIGJhYnkvY2hpbGQgYWdlZ3JvdXAgY29sdW1uCmRhdGEgPC0gZGF0YSAlPiUgCiAgbXV0YXRlKGFnZWdyb3VwID0gYWdlIDwgMi4wKSAKZGF0YSRhZ2Vncm91cCA8LSBhcy5mYWN0b3IoZGF0YSRhZ2Vncm91cCkKZGF0YSRhZ2Vncm91cCA8LSBmY3RfcmVjb2RlKGRhdGEkYWdlZ3JvdXAsIGJhYnkgPSAiVFJVRSIsIGNoaWxkID0gIkZBTFNFIikKYGBgCgpBbmQgb3VyIHBhcnRpY2lwYW50IHRhYmxlLiAKYGBge3J9CnBhcnRpY2lwYW50c19iIDwtIGRhdGEgJT4lCiAgZmlsdGVyKGFnZWdyb3VwPT0iYmFieSIpICU+JQogIHNlbGVjdChwYXJ0aWNpcGFudCwgZ2VuZGVyLCBsYW5ndWFnZSwgYWdlKSAlPiUKICBkaXN0aW5jdCgpCgpwYXJ0aWNpcGFudHNfYl9uIDwtIHBhcnRpY2lwYW50c19iICU+JQogIGNvdW50KGdlbmRlciwgbGFuZ3VhZ2UpICU+JQogIHNwcmVhZChnZW5kZXIsIG4pCgpwYXJ0aWNpcGFudHNfYl9hZ2UgPC0gcGFydGljaXBhbnRzX2IgJT4lCiAgZ3JvdXBfYnkobGFuZ3VhZ2UpICU+JQogIHN1bW1hcmlzZShhZ2VfbSA9IHJvdW5kKG1lYW4oYWdlKSwgMSksIAogICAgICAgICAgICBhZ2Vfc2QgPSByb3VuZChzZChhZ2UpLCAxKSwKICAgICAgICAgICAgYWdlX21pbiA9IHJhbmdlKGFnZSlbMV0sCiAgICAgICAgICAgIGFnZV9tYXggPSByYW5nZShhZ2UpWzJdKSAlPiUKICBtdXRhdGUoYWdlX3JhbmdlID0gcGFzdGUoYWdlX21pbiwgYWdlX21heCwgc2VwID0gIiAtICIpKSAlPiUKICBzZWxlY3QoLWFnZV9taW4sIC1hZ2VfbWF4KSAlPiUKICBtdXRhdGUoYWdlX21lYW4gPSBwYXN0ZShhZ2VfbSwgYWdlX3NkLCBzZXAgPSAiwrEiKSkgJT4lCiAgc2VsZWN0KC1hZ2VfbSwgLWFnZV9zZCkgJT4lCiAgc2VsZWN0KGxhbmd1YWdlLCBhZ2VfbWVhbiwgYWdlX3JhbmdlKQoKcGFydGljaXBhbnRzX3RhYmxlX2IgPC0gbGVmdF9qb2luKHBhcnRpY2lwYW50c19iX24sIHBhcnRpY2lwYW50c19iX2FnZSwgYnkgPSAibGFuZ3VhZ2UiKSAlPiUKICBhZGRfY29sdW1uKGFnZWdyb3VwID0gImJhYnkiKQoKcGFydGljaXBhbnRzX2MgPC0gZGF0YSAlPiUKICBmaWx0ZXIoYWdlZ3JvdXA9PSJjaGlsZCIpICU+JQogIHNlbGVjdChwYXJ0aWNpcGFudCwgZ2VuZGVyLCBsYW5ndWFnZSwgYWdlKSAlPiUKICBkaXN0aW5jdCgpCgpwYXJ0aWNpcGFudHNfY19uIDwtIHBhcnRpY2lwYW50c19jICU+JQogIGNvdW50KGdlbmRlciwgbGFuZ3VhZ2UpICU+JQogIHNwcmVhZChnZW5kZXIsIG4pCgpwYXJ0aWNpcGFudHNfY19hZ2UgPC0gcGFydGljaXBhbnRzX2MgJT4lCiAgZ3JvdXBfYnkobGFuZ3VhZ2UpICU+JQogIHN1bW1hcmlzZShhZ2VfbSA9IHJvdW5kKG1lYW4oYWdlKSwgMSksIAogICAgICAgICAgICBhZ2Vfc2QgPSByb3VuZChzZChhZ2UpLCAxKSwKICAgICAgICAgICAgYWdlX21pbiA9IHJhbmdlKGFnZSlbMV0sCiAgICAgICAgICAgIGFnZV9tYXggPSByYW5nZShhZ2UpWzJdKSAlPiUKICBtdXRhdGUoYWdlX3JhbmdlID0gcGFzdGUoYWdlX21pbiwgYWdlX21heCwgc2VwID0gIiAtICIpKSAlPiUKICBzZWxlY3QoLWFnZV9taW4sIC1hZ2VfbWF4KSAlPiUKICBtdXRhdGUoYWdlX21lYW4gPSBwYXN0ZShhZ2VfbSwgYWdlX3NkLCBzZXAgPSAiwrEiKSkgJT4lCiAgc2VsZWN0KC1hZ2VfbSwgLWFnZV9zZCkgJT4lCiAgc2VsZWN0KGxhbmd1YWdlLCBhZ2VfbWVhbiwgYWdlX3JhbmdlKQoKcGFydGljaXBhbnRzX3RhYmxlX2MgPC0gbGVmdF9qb2luKHBhcnRpY2lwYW50c19jX24sIHBhcnRpY2lwYW50c19jX2FnZSwgYnkgPSAibGFuZ3VhZ2UiKSAlPiUKICBhZGRfY29sdW1uKGFnZWdyb3VwID0gImNoaWxkIikKCnJiaW5kKHBhcnRpY2lwYW50c190YWJsZV9iLCBwYXJ0aWNpcGFudHNfdGFibGVfYykgJT4lIAogIHNlbGVjdChsYW5ndWFnZSwgYWdlZ3JvdXAsIEZlbWFsZSwgTWFsZSwgYWdlX21lYW4sIGFnZV9yYW5nZSkKYGBgCgojIyBTYXZlIQpHcmVhdC4gTGV0J3Mgc2F2ZSB0aGlzIGFzIGBjbGVhbmVkY2hpbGR4eWRhdGEuY3N2Jy4gCgpgYGB7cn0KIyBQdWxsIGFwYXJ0IGNvbmRpdGlvbiBjb2x1bW5zCmRhdGEgPC0gZGF0YSAlPiUKICBzZXBhcmF0ZShjb25kaXRpb24sIGludG8gPSBjKCJzdG9yeSIsICJjbGlwbnVtIiwgImRpcmVjdGlvbiIsICJtZWRpYSIpLCBzZXAgPSAiXyIpICU+JQogIHVuaXRlKHN0b3J5LCBjbGlwbnVtLCBjb2wgPSAic3RvcnkiLCBzZXAgPSAiXyIpICU+JQogIHNlbGVjdCgtbWVkaWEpIAoKIyBBIGJpdCBtb3JlIGNsZWFuaW5nIHVwCmRhdGEgPC0gZGF0YSAlPiUKICBtdXRhdGUoZGlyZWN0aW9uID0gY2FzZV93aGVuKAogICAgZGlyZWN0aW9uID09ICJGVyIgfiAiZm9yd2FyZCIsCiAgICBkaXJlY3Rpb24gPT0gIkVSIiB+ICJyZXZlcnNlZCIKICApKSAlPiUKICBtdXRhdGUobGFuZ3VhZ2UgPSBjYXNlX3doZW4oCiAgICBsYW5ndWFnZSA9PSAiU2lnbkxhbmd1YWdlRXhwb3NlZCIgfiAiU0UiLAogICAgbGFuZ3VhZ2UgPT0gIkVuZ2xpc2hFeHBvc2VkIiB+ICJOU0UiCiAgKSkgJT4lCiAgbXV0YXRlKGdyb3VwID0gYXMuZmFjdG9yKGdyb3VwKSwKICAgICAgICAgZ2VuZGVyID0gYXMuZmFjdG9yKGdlbmRlciksCiAgICAgICAgIGxhbmd1YWdlID0gYXMuZmFjdG9yKGxhbmd1YWdlKSwKICAgICAgICAgc3RvcnkgPSBhcy5mYWN0b3Ioc3RvcnkpLAogICAgICAgICBkaXJlY3Rpb24gPSBhcy5mYWN0b3IoZGlyZWN0aW9uKSkKCiMgU2F2ZSBhcyBjc3YgYW5kIGZlYXRoZXIgKGZlYXRoZXIgcHJlc2VydmVzIGNvbHVtbiB0eXBlcyBmb3IgUikKd3JpdGVfY3N2KGRhdGEsIi4uL0NoaWxkIERhdGEvY2xlYW5lZGNoaWxkeHlkYXRhLmNzdiIpCndyaXRlX2ZlYXRoZXIoZGF0YSwiLi4vQ2hpbGQgRGF0YS9jbGVhbmVkY2hpbGR4eWRhdGEuZmVhdGhlciIpCmBgYAoKIyMgQW55IG90aGVyIGRhdGEgY2xlYW51cD8/IApEbyB3ZSBuZWVkIHRvIGRvIGFueSBvdGhlciBjbGVhbnVwPyBJIGRvbid0IHRoaW5rIHNvLiAKCiMgTWVhbnMgdnMgTWVkaWFucwoKRmlyc3QsIGxldCdzIHRyaW0gZWFjaCBwYXJ0aWNpcGFudCdzIGRhdGEsIGdldHRpbmcgcmlkIG9mIHRoZSBmaXJzdCA2MCBzYW1wbGVzICgwLjUgc2VjcykuIFRoZW4gd2UnbGwgZ2V0IHRoZSB0aGUgbWVhbiB4IGFuZCB5IGNvb3JkaW5hdGUgZm9yIGVhY2ggc3RvcnkgZm9yIGVhY2ggcGFydGljaXBhbnQuCgpgYGB7cn0KIyBKdXN0IHRvIGxvYWQgZGF0YSBhZ2FpbiAKZGF0YSA8LSByZWFkX2ZlYXRoZXIoIi4uL0NoaWxkIERhdGEvY2xlYW5lZGNoaWxkeHlkYXRhLmZlYXRoZXIiKQoKZGF0YSA8LSBkYXRhICU+JQogIGdyb3VwX2J5KHBhcnRpY2lwYW50LHRyaWFsKSAlPiUKICBzbGljZSg2MDpuKCkpCgpkYXRhX2NlbnRyYWxfdGVuZGVuY2llcyA8LSBkYXRhICU+JQogIGdyb3VwX2J5KGxhbmd1YWdlLCBhZ2Vncm91cCwgcGFydGljaXBhbnQsIHRyaWFsKSAlPiUKICBzdW1tYXJpc2UobWVhbl94ID0gbWVhbih4LG5hLnJtPVRSVUUpLAogICAgICAgICAgICBtZWFuX3kgPSBtZWFuKHksbmEucm09VFJVRSksCiAgICAgICAgICAgIG1lZGlhbl94ID0gbWVkaWFuKHgsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICBtZWRpYW5feSA9IG1lZGlhbih5LCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgZGlmZl94ID0gbWVhbl94IC0gbWVkaWFuX3gsCiAgICAgICAgICAgIGRpZmZfeSA9IG1lYW5feSAtIG1lZGlhbl95KQoKbWVhbnMgPC0gZGF0YV9jZW50cmFsX3RlbmRlbmNpZXMgJT4lCiAgZ3JvdXBfYnkobGFuZ3VhZ2UsIGFnZWdyb3VwLCBwYXJ0aWNpcGFudCkgJT4lCiAgc3VtbWFyaXNlKG1lYW5feCA9IG1lYW4obWVhbl94LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBtZWFuX3kgPSBtZWFuKG1lYW5feSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ3JvdXBfYnkobGFuZ3VhZ2UsIGFnZWdyb3VwKSAlPiUKICBzdW1tYXJpc2Uoc2RfeCA9IHNkKG1lYW5feCksCiAgICAgICAgICAgIHNkX3kgPSBzZChtZWFuX3kpLAogICAgICAgICAgICBuID0gbigpLAogICAgICAgICAgICBtZWFuX3ggPSBtZWFuKG1lYW5feCksCiAgICAgICAgICAgIG1lYW5feSA9IG1lYW4obWVhbl95KSotMSwKICAgICAgICAgICAgc2VfeCA9IHNkX3gvc3FydChuKSwKICAgICAgICAgICAgc2VfeSA9IHNkX3kvc3FydChuKSkKCm1lYW5zCgptZWFuc19lcnJvciA8LSBtZWFucyAlPiUKICBzZWxlY3QoLW4sIC1zZF94LCAtc2RfeSkgJT4lCiAgZ2F0aGVyKG1lYXN1cmUsIHZhbHVlLCBtZWFuX3g6c2VfeSkgJT4lCiAgc2VwYXJhdGUobWVhc3VyZSwgaW50byA9IGMoIm1lYXN1cmUiLCJheGlzIikpICU+JQogIHNwcmVhZChtZWFzdXJlLCB2YWx1ZSkKCm1lYW5zX2Vycm9yICU+JQogIGZpbHRlcihheGlzID09ICJ4IikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYWdlZ3JvdXAsIHkgPSBtZWFuLCBjb2xvciA9IGxhbmd1YWdlLCBncm91cCA9IGxhbmd1YWdlKSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW4tc2UsIHltYXggPSBtZWFuK3NlKSwgCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwgd2lkdGggPSAwLjI1LCBzaXplID0gMC41KSArIAogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsMTA4MCkpICsKICBjb29yZF9mbGlwKCkgKyAKICBsYWJzKHkgPSAibWVhbiBhbG9uZyB4IGF4aXMiLCB0aXRsZSA9ICJYLUF4aXMgTWVhbnMiKQoKbWVhbnNfZXJyb3IgJT4lCiAgZmlsdGVyKGF4aXMgPT0gInkiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBhZ2Vncm91cCwgeSA9IG1lYW4sIGNvbG9yID0gbGFuZ3VhZ2UsIGdyb3VwID0gbGFuZ3VhZ2UpKSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCkpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbi1zZSwgeW1heCA9IG1lYW4rc2UpLCAKICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLCB3aWR0aCA9IDAuMjUsIHNpemUgPSAwLjUpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTcyMCwwKSkgKwogIGxhYnMoeSA9ICJtZWFuIGFsb25nIHkgYXhpcyIsIHRpdGxlID0gIlktQXhpcyBNZWFucyIpCmBgYAoKIyMgRGlzdHJpYnV0aW9uCkJ1dCBpcyB0aGUgeS12YWx1ZSBkaXN0cmlidXRpb24gdW5pbW9kYWwsIGJpbW9kYWwsIG5vcm1hbCwgd2hhdD8gRG8gdGhlIG1lYW5zIHJlcHJlc2VudCB0aGUgb25seSBwZWFrPyBMZXQncyBnZXQgaGlzdG9ncmFtcy4KCmBgYHtyfQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSB5KSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwKSArIGZhY2V0X2dyaWQoYWdlZ3JvdXAgfiBsYW5ndWFnZSkgKwogIGdndGl0bGUoIkhpc3RvZ3JhbXMgb2YgYWxsIHktdmFsdWVzIGluIGFsbCBzdG9yaWVzIikKYGBgCgpNYXliZSB0aGUgbWl4dHVyZSBvZiBzdG9yaWVzIGFuZCBkaXJlY3Rpb25zIHRocm93cyBvZmYgdGhlIGhpc3RvZ3JhbXMuIExldCdzIGJyZWFrIGl0IGRvd24gYnkgIm1hcmsiIHdoaWNoIGlzIGFuIHVuaXF1ZSBudW1iZXIgSSBhc3NpZ25lZCB0byBlYWNoIHN0b3J5L2RpcmVjdGlvbi4gCgpgYGB7ciBmaWcuaGVpZ2h0PTEyfQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSB5KSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwKSArIGZhY2V0X2dyaWQobWFyayB+IGFnZWdyb3VwKSArCiAgZ2d0aXRsZSgiSGlzdG9ncmFtcyBvZiBhbGwgeS12YWx1ZXMgYnkgZWFjaCBzdG9yeS9tYXJrIikKYGBgCgpTdGlsbCBzZWVtcyBtb3N0bHkgdW5pbW9kYWwgKHRoYXQgbWVhbnMgb25lIHBlYWssIHJpZ2h0PykuIAoKIyMgU2tld25lc3MKQnV0IGlzIHRoZSBkYXRhIHNrZXdlZD8gSSd2ZSBiZWVuIHdvbmRlcmluZyBpZiB3ZSBzaG91bGQgYmUgdXNpbmcgTUVESUFOUyBiZWNhdXNlIHRoZXJlIGNhbiBiZSBzb21lIGV4dHJlbWUgeCBhbmQgeSB2YWx1ZXMuIEJ1dCBSYWluIHNhaWQgdGhlcmUncyBiZWVuIGNyaXRpY2lzbSBvZiB1c2luZyBtZWRpYW5zIGFuZCB0aGF0IG1lYW5zIGFyZSBiZXR0ZXIgb3ZlcmFsbC4gTGV0J3MgaGF2ZSBhIGxvb2suIAoKVGhlIGZpcnN0IGNoYXJ0IHNob3dzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW4gYW5kIHRoZSBtZWRpYW4gZm9yIGVhY2ggcGFydGljaXBhbnQgYW5kIHRyaWFsLiBQb3NpdGl2ZSBtZWFucyB0aGUgbWVhbiBpcyBiaWdnZXIgdGhhbiB0aGUgbWVkaWFuLCBuZWdhdGl2ZSBtZWFucyB0aGUgbWVkaWFuIGlzIGJpZ2dlci4gSXQgc2hvd3MgdGhlcmUgaXMgc29tZSBza2V3IGZvciB0aGUgeS1heGlzLi4uYnV0IHRoZSB2YXN0IG1ham9yaXR5IG9mIGRpZmZlcmVuY2VzIGlzIGxlc3MgdGhhbiA1MCBweCBzbyBtYXliZSBpdCdzIG9rYXkuIAoKVGhlIHNlY29uZCBjaGFydCBzaG93cyB0aGUgbWVhbnMgYW5kIG1lZGlhbnMgdGhlbXNlbHZlcy4gQW5kIHRoZSBzcHJlYWQgaXMgcHJldHR5IHNpbWlsYXIgYmV0d2VlbiBtZWFuIGFuZCBtZWRpYW4gc28gbWF5YmUgdXNpbmcgbWVhbnMgaXMgZmluZS4KCmBgYHtyfQpkYXRhX2NlbnRyYWxfdGVuZGVuY2llcyAlPiUKICBnYXRoZXIobWVhc3VyZSwgdmFsdWUsIGRpZmZfeDpkaWZmX3kpICU+JQogIGdncGxvdChhZXMoeCA9IHZhbHVlKSkgKyBnZW9tX2hpc3RvZ3JhbSgpICsgZmFjZXRfZ3JpZCguIH4gbWVhc3VyZSkKCmRhdGFfY2VudHJhbF90ZW5kZW5jaWVzICU+JQogIGdhdGhlcihtZWFzdXJlLCB2YWx1ZSwgbWVhbl94Om1lZGlhbl95KSAlPiUKICBzZXBhcmF0ZShtZWFzdXJlLCBpbnRvID0gYygibWVhc3VyZSIsImF4aXMiKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdmFsdWUpKSArIGdlb21faGlzdG9ncmFtKCkgKyBmYWNldF9ncmlkKG1lYXN1cmUgfiBheGlzKQpgYGAKCiMjIFRlc3RpbmcgdGhlIE1lYW5zCkxldCdzIHJ1biBhIExNTSBvbiB0aGUgbWVhbnMuIEZpcnN0LCB4IG1lYW5zIGZvciBiYWJpZXMuIApgYGB7cn0KbWVhbnMgPC0gZGF0YSAlPiUKICBncm91cF9ieShsYW5ndWFnZSwgYWdlZ3JvdXAsIHBhcnRpY2lwYW50LCBhZ2UsIHN0b3J5LCBkaXJlY3Rpb24sIHRyaWFsLCByZXBldGl0aW9uKSAlPiUKICBzdW1tYXJpc2UoeCA9IG1lYW4oeCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgeSA9IG1lYW4oeSwgbmEucm0gPSBUUlVFKSkKCm1lYW5zJHJlcGV0aXRpb24gPSBhcy5mYWN0b3IobWVhbnMkcmVwZXRpdGlvbikKbWVhbnMkdHJpYWwgPSBhcy5mYWN0b3IobWVhbnMkdHJpYWwpCgpsbW1fYmFieV9tZWFuX3ggPC0gbG1lcih4IH4gbGFuZ3VhZ2UgKiBkaXJlY3Rpb24gKyBhZ2UgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAoMXxzdG9yeSkgKyAoMXxwYXJ0aWNpcGFudCkgKyAoMXxyZXBldGl0aW9uKSArICgxfHRyaWFsKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBmaWx0ZXIobWVhbnMsIGFnZWdyb3VwID09ICJiYWJ5IikpCnN1bW1hcnkobG1tX2JhYnlfbWVhbl94KQpgYGAKClkgbWVhbnMgZm9yIGJhYmllcwpgYGB7cn0KbG1tX2JhYnlfbWVhbl95IDwtIGxtZXIoeSB+IGxhbmd1YWdlICogZGlyZWN0aW9uICsgYWdlICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgKDF8c3RvcnkpICsgKDF8cGFydGljaXBhbnQpICsgKDF8cmVwZXRpdGlvbikgKyAoMXx0cmlhbCksIAogICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZmlsdGVyKG1lYW5zLCBhZ2Vncm91cCA9PSAiYmFieSIpKQpzdW1tYXJ5KGxtbV9iYWJ5X21lYW5feSkKYGBgCgpYIG1lYW5zIGZvciBjaGlsZHJlbgpgYGB7cn0KbG1tX2NoaWxkX21lYW5feCA8LSBsbWVyKHggfiBsYW5ndWFnZSAqIGRpcmVjdGlvbiArIGFnZSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICgxfHN0b3J5KSArICgxfHBhcnRpY2lwYW50KSArICgxfHJlcGV0aXRpb24pICsgKDF8dHJpYWwpLCAKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGZpbHRlcihtZWFucywgYWdlZ3JvdXAgPT0gImNoaWxkIikpCnN1bW1hcnkobG1tX2NoaWxkX21lYW5feCkKYGBgCgpZIG1lYW5zIGZvciBjaGlsZHJlbgpgYGB7cn0KbG1tX2NoaWxkX21lYW5feSA8LSBsbWVyKHkgfiBsYW5ndWFnZSAqIGRpcmVjdGlvbiArIGFnZSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICgxfHN0b3J5KSArICgxfHBhcnRpY2lwYW50KSArICgxfHJlcGV0aXRpb24pICsgKDF8dHJpYWwpLCAKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGZpbHRlcihtZWFucywgYWdlZ3JvdXAgPT0gImNoaWxkIikpCnN1bW1hcnkobG1tX2NoaWxkX21lYW5feSkKYGBgCgpMZXQncyB0cnkgaXQgd2l0aCBib3RoIGtpZHMgYW5kIGJhYmllcy4gCmBgYHtyfQpsbW1fYWxsX21lYW5feCA8LSBsbWVyKHggfiBsYW5ndWFnZSAqIGRpcmVjdGlvbiAqIGFnZWdyb3VwICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgKDF8c3RvcnkpICsgKDF8cGFydGljaXBhbnQpICsgKDF8cmVwZXRpdGlvbikgKyAoMXx0cmlhbCksIAogICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gbWVhbnMpCnN1bW1hcnkobG1tX2FsbF9tZWFuX3gpCmxtbV9hbGxfbWVhbl95IDwtIGxtZXIoeSB+IGxhbmd1YWdlICogZGlyZWN0aW9uICogYWdlZ3JvdXAgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAoMXxzdG9yeSkgKyAoMXxwYXJ0aWNpcGFudCkgKyAoMXxyZXBldGl0aW9uKSArICgxfHRyaWFsKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBtZWFucykKc3VtbWFyeShsbW1fYWxsX21lYW5feSkKYGBgCgojIyBTdW1tYXJ5Ck5vIGRpZmZlcmVuY2UgaW4gdGhlIG1lYW4gbG9va2luZyBwb3NpdGlvbiBmb3IgeCBvciB5IGluIGNoaWxkcmVuIG9yIGJhYmllcyEgQnV0IGlmIHdlIHB1dCBjaGlsZHJlbiBhbmQgYmFiaWVzIGluIHRoZSBzYW1lIGRhdGFzZXQgd2UgZ2V0IGEgc2lnbmlmaWNhbnQgbWFpbiBlZmZlY3Qgb2YgY2hpbGRyZW4gdnMuIGJhYmllcy4gT2theS4gCgojIFBsb3R0aW5nIE9uZSBLaWQKCkFuZCBJIGNhbiBnZXQgeCBvciB5IHBsb3RzIG9mIG9uZSBwYXJ0aWNpcGFudCBhY3Jvc3MgOCBzdG9yaWVzLiBMZXQncyBkbyBFbW1ldC4gV2UnbGwgc2V0IHRoZSB4IGFuZCB5IGxpbWl0cyB0byB0aGUgd2hvbGUgd2lkdGggb2YgdGhlIFRvYmlpIG1vbml0b3IgKDE2MDB4MTIwMC4uLm9yIGlzIGl0IG5vdyAxMDgweDcyMCkuIEJ1dCBiZWNhdXNlIFRvYmlpIGNvbnNpZGVycyAoMCwwKSB0byBiZSB0aGUgdXBwZXIgbGVmdCBjb3JuZXIgKGFuZCBub3QgdGhlIGJvdHRvbSBsZWZ0IGNvcm5lciksIHdlIGFsc28gbmVlZCB0byBmbGlwIHRoZSB5IGF4aXMuIAoKYGBge3J9CmVtbWV0IDwtIGZpbHRlcihkYXRhLHBhcnRpY2lwYW50PT0iZW1tZXRfMTJfMTBfMTJfQ09EQSIpICU+JSBtdXRhdGUoeSA9IHkqLTEpCmdncGxvdChlbW1ldCxhZXMoeD14LHk9eSxjb2xvcj1zdG9yeSkpICsgZ2VvbV9wb2ludChzaXplPTAuMSkgKyBnZW9tX3BhdGgoKSArIGZhY2V0X2dyaWQocmVwZXRpdGlvbiB+IHN0b3J5KSArIGd1aWRlcyhjb2xvcj0ibm9uZSIpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0PWMoMCwxMDgwKSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGltaXQ9YygtNzIwLDApKQpgYGAKCkNvb2wsIHllYWg/IAoKIyBWaWV3aW5nIFNwYWNlIChTRCkKVG8gbWVhc3VyZSB2aWV3aW5nIHNwYWNlLCB3ZSBjYW4gdXNlIHN0YW5kYXJkIGRldmlhdGlvbiBvciBJUVIuIEdlbmVyYWxseSwgaWYgd2UncmUgdXNpbmcgbWVhbnMsIHdlIHNob3VsZCB1c2Ugc3RhbmRhcmQgZGV2aWF0aW9ucy4gSWYgd2UncmUgdXNpbmcgbWVkaWFucywgd2Ugc2hvdWxkIHVzZSBJUVIuIFRoYXQncyBteSB0aGlua2luZywgYW55d2F5LiAKCldlJ2xsIHRyeSBTRHMgZmlyc3QuIExldCdzIHRyeSB0aGUgZmlyc3QgU0QsIHdoaWNoIGlzIHRoZSBtaWRkbGUgNjglIG9mIHRoZSBkYXRhLiAKCmBgYHtyfQpzZCA8LSBkYXRhICU+JQogIGdyb3VwX2J5KHBhcnRpY2lwYW50LCB0cmlhbCkgJT4lCiAgc3VtbWFyaXNlKG1lYW5feCA9IG1lYW4oeCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgbWVhbl95ID0gbWVhbih5LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBzZF94ID0gc2QoeCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgc2RfeSA9IHNkKHksIG5hLnJtID0gVFJVRSkpICU+JQogIHVuZ3JvdXAoKQpoZWFkKHNkLDEwKQoKIyBqb2luIHBhcnRpY2lwYW50IGluZm8gYmFjawpwYXJ0aWNpcGFudGluZm8gPC0gZGF0YSAlPiUKICBzZWxlY3QocGFydGljaXBhbnQsIHRyaWFsLCBhZ2UsIGdyb3VwLCBhZ2Vncm91cCwgZ2VuZGVyLCBsYW5ndWFnZSwgc3RvcnksIGRpcmVjdGlvbiwgbWFyaywgcmVwZXRpdGlvbikgJT4lCiAgZGlzdGluY3QoKQpzZCA8LSBsZWZ0X2pvaW4oc2QsIHBhcnRpY2lwYW50aW5mbywgYnkgPSBjKCJwYXJ0aWNpcGFudCIsInRyaWFsIikpCmBgYAoKQW5kIGNoZWNrIG91dCB0aGUgaGlzdG9ncmFtcy4gSSB0cnVuY2F0ZWQgdGhlIHktYXhpcyBhdCA1MCBjb3VudHMgdG8gYmV0dGVyIHNlZSBvdXRsaWVycy4gCgpgYGB7cn0Kc2QgJT4lIAogIGdhdGhlcihheGlzLHNkLHNkX3g6c2RfeSkgJT4lCiAgZ2dwbG90KGFlcyh4PXNkLGZpbGw9YXhpcykpICsgZ2VvbV9oaXN0b2dyYW0oKSArIGZhY2V0X2dyaWQoYXhpc34uKSArIAogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDUwKSkKYGBgCgpTbyB0aGVyZSBhcmUgc29tZSByZWFsbHkgaGlnaCBvdXRsaWVycyB3aGVyZSB0aGUgU0QgaXMgMTUwIG9yIDIwMCBwaXhlbHMgaW4gb25lIGRpcmVjdGlvbiAoc28gYSBzcHJlYWQgb2YgYXMgaGlnaCBhcyA0MDAgcGl4ZWxzLCB3aGljaCBpcyBhIGxvdCEgSSB3YW50IHRvIHNlZSB0aG9zZSBjYXNlcyB0byBzZWUgaWYgdGhleSBzaG91bGQgYmUgdGFrZW4gb3V0IG9yIGlmIHdlIGRvbid0IG5lZWQgdG8gd29ycnkgYWJvdXQgdGhlbS4gCgo+IEl0IG1heSBiZSB1c2VmdWwgdG8gdGhpbmsgYWJvdXQgZ2V0dGluZyByaWQgb2Ygb3V0bGllcnMuIFdlIHNob3VsZCBrZWVwIHRoaXMgaW4gbWluZC4uLgoKYGBge3J9Cgp4b3V0bGllcnMgPC0gc2QgJT4lCiAgYXJyYW5nZShkZXNjKHNkX3gpKSAlPiUKICBzbGljZSgxOjIwKQp5b3V0bGllcnMgPC0gc2QgJT4lCiAgYXJyYW5nZShkZXNjKHNkX3kpKSAlPiUKICBzbGljZSgxOjIwKQp4b3V0bGllcnMKeW91dGxpZXJzCgpgYGAKCiMjIFRlc3RpbmcKRmlyc3QsIGRvZXMgcmV2ZXJzYWwgYW5kIGxhbmd1YWdlIGV4cGVyaWVuY2UgaGF2ZSBhbiBlZmZlY3Qgb24gdGhlIFNEPyBCYWJpZXMsIHgtYXhpcyBmaXJzdC4gCgpgYGB7cn0Kc2QkdHJpYWwgPC0gYXMuZmFjdG9yKHNkJHRyaWFsKQpzZCRyZXBldGl0aW9uIDwtIGFzLmZhY3RvcihzZCRyZXBldGl0aW9uKQoKc2RfeF9iYWJ5IDwtIGxtZXIoc2RfeCB+IGRpcmVjdGlvbiAqIGxhbmd1YWdlICsgYWdlICsgKDF8cGFydGljaXBhbnQpICsgKDF8c3RvcnkpICsgKDF8cmVwZXRpdGlvbikgKyAoMXx0cmlhbCksIGRhdGEgPSBmaWx0ZXIoc2QsIGFnZWdyb3VwID09ICJiYWJ5IikpCnN1bW1hcnkoc2RfeF9iYWJ5KQpgYGAKClRoYXQncyBmaW5lLCB3ZSdyZSBub3QgZXhhY3RseSBwcmVkaWN0aW5nIGNoYW5nZXMgYWxvbmcgdGhlIHgtYXhpcy4gVGhlIHktYXhpcyBpcyB3aGF0IHdlIGFyZSByZWFsbHkgaW50ZXJlc3RlZCBpbiEgOikgCmBgYHtyfQpzZF95X2JhYnkgPC0gbG1lcihzZF95IH4gZGlyZWN0aW9uICogbGFuZ3VhZ2UgKyBhZ2UgKyAoMXxwYXJ0aWNpcGFudCkgKyAoMXxzdG9yeSkgKyAoMXxyZXBldGl0aW9uKSArICgxfHRyaWFsKSwgZGF0YSA9IGZpbHRlcihzZCwgYWdlZ3JvdXAgPT0gImJhYnkiKSkKc3VtbWFyeShzZF95X2JhYnkpCmBgYAoKTm93IGNoaWxkcmVuLCB4LWF4aXMKYGBge3J9CnNkX3hfY2hpbGQgPC0gbG1lcihzZF94IH4gZGlyZWN0aW9uICogbGFuZ3VhZ2UgKyBhZ2UgKyAoMXxwYXJ0aWNpcGFudCkgKyAoMXxzdG9yeSkgKyAoMXxyZXBldGl0aW9uKSArICgxfHRyaWFsKSwgZGF0YSA9IGZpbHRlcihzZCwgYWdlZ3JvdXAgPT0gImNoaWxkIikpCnN1bW1hcnkoc2RfeF9jaGlsZCkKYGBgCgpBbmQgY2hpbGRyZW4sIHktYXhpcwpgYGB7cn0Kc2RfeV9jaGlsZCA8LSBsbWVyKHNkX3kgfiBkaXJlY3Rpb24gKiBsYW5ndWFnZSArIGFnZSArICgxfHBhcnRpY2lwYW50KSArICgxfHN0b3J5KSArICgxfHJlcGV0aXRpb24pICsgKDF8dHJpYWwpLCBkYXRhID0gZmlsdGVyKHNkLCBhZ2Vncm91cCA9PSAiY2hpbGQiKSkKc3VtbWFyeShzZF95X2NoaWxkKQpgYGAKCkFuZCBub3cgYWxsIGJhYmllcy9jaGlsZHJlbiwgeCBheGlzCmBgYHtyfQpzZF94X2FsbCA8LSBsbWVyKHNkX3ggfiBkaXJlY3Rpb24gKiBsYW5ndWFnZSAqIGFnZWdyb3VwICsgKDF8cGFydGljaXBhbnQpICsgKDF8c3RvcnkpICsgKDF8cmVwZXRpdGlvbikgKyAoMXx0cmlhbCksIGRhdGEgPSBzZCkKc3VtbWFyeShzZF94X2FsbCkKYGBgCgpgYGB7cn0Kc2RfeV9hbGwgPC0gbG1lcihzZF95KjIgfiBkaXJlY3Rpb24gKiBsYW5ndWFnZSAqIGFnZWdyb3VwICsgKDF8cGFydGljaXBhbnQpICsgKDF8c3RvcnkpICsgKDF8cmVwZXRpdGlvbikgKyAoMXx0cmlhbCksIGRhdGEgPSBzZCkKc3VtbWFyeShzZF95X2FsbCkKYGBgCgojIyBTdW1tYXJ5ClNvIHRoZXJlIGlzIG5vIGVmZmVjdCBvZiBsYW5ndWFnZSBvciBkaXJlY3Rpb24gKG9yIGludGVyYWN0aW9ucykgb24gdGhlIHN0YW5kYXJkIGRldmlhdGlvbi4gQW1vbmcgYmFiaWVzLCB0aGVyZSBzZWVtcyB0byBiZSBhbiBlZmZlY3Qgb2YgYWdlIG9uIHktYXhpcyB2aWV3aW5nIHNwYWNlIHN1Y2ggdGhhdCBpdCBuYXJyb3dzIHRoZSBvbGRlciB0aGUgYmFieSBpcyAocCA9IDAuMDQ2KS4gCgpXaGVuIHdlIHB1dCBiYWJpZXMgYW5kIGNoaWxkcmVuIHRvZ2V0aGVyLCB3ZSBzZWUgYWdlIGdyb3VwIGRpZmZlcmVuY2VzIGZvciBzZF94IGFuZCBzZF95LCBub3Qgc3VycHJpc2luZ2x5LiAKCgojIEV2ZXJ5dGhpbmcgYWZ0ZXIgdGhpcyBuZWVkcyB0byBiZSB1cGRhdGVkLgoKIyBWaWV3aW5nIFNwYWNlIChJUVIpCgpOb3cgbGV0J3MgZ2V0IHRoZSBtaWRkbGUgNTAlIChha2EgdGhlIElRUikgb2YgeCBhbmQgeSBmb3IgZWFjaCBwYXJ0aWNpcGFudCdzIHN0b3J5ICh3ZSd2ZSBhbHJlYWR5IHRyaW1tZWQgdGhlIGZpcnN0IDYwIHNhbXBsZXMpLiBUaGF0IHNob3VsZCBhbHNvIHRha2UgY2FyZSBvZiBmdXJ0aGVyIHdlaXJkIG91dGxpZXJzLiBBbmQgd2UgYXJlIGRlZmluaW5nICJ2aWV3aW5nIHNwYWNlIiBhcyB0aGUgSVFSIG9mIHRoZSB4IGFuZCB5IGF4aXMuIAoKYGBge3J9CmlxciA8LSBkYXRhICU+JQogIGdyb3VwX2J5KHBhcnRpY2lwYW50LHRyaWFsKSAlPiUKICBzdW1tYXJpc2UoeElRUiA9IElRUih4LG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgeUlRUiA9IElRUih5LG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgeG1lZCA9IG1lZGlhbih4LCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHltZWQgPSBtZWRpYW4oeSwgbmEucm09VFJVRSkpICU+JQogIHVuZ3JvdXAoKQpoZWFkKGlxciwxMCkKCiMgSm9pbiBwYXJ0aWNpcGFudCBpbmZvIGJhY2sgaW50byBJUVIgdGFibGUKcGFydGljaXBhbnRpbmZvIDwtIGRhdGEgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50LCB0cmlhbCwgYWdlLCBncm91cCwgZ2VuZGVyLCBsYW5ndWFnZSwgc3RvcnksIGRpcmVjdGlvbiwgbWFyaywgcmVwZXRpdGlvbikgJT4lCiAgZGlzdGluY3QoKQoKaXFyIDwtIGxlZnRfam9pbihpcXIsIHBhcnRpY2lwYW50aW5mbywgYnkgPSBjKCJwYXJ0aWNpcGFudCIsInRyaWFsIikpCmBgYAoKQW5kIGNoZWNrIG91dCB0aGUgaGlzdG9ncmFtcy4gSSB0cnVuY2F0ZWQgdGhlIHktYXhpcyBhdCAxMDAgdG8gYmV0dGVyIHNlZSBvdXRsaWVycy4gCgpgYGB7cn0KaXFyICU+JSAKICBnYXRoZXIoYXhpcyxpcXIseElRUjp5SVFSKSAlPiUKICBnZ3Bsb3QoYWVzKHg9aXFyLGZpbGw9YXhpcykpICsgZ2VvbV9oaXN0b2dyYW0oKSArIGZhY2V0X2dyaWQoYXhpc34uKSArIAogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDUwKSkKYGBgCgpTbyB3ZSBzZWUgc29tZSBvdXRsaWVycy4gV2hvIGFyZSB0aG9zZT8gTGV0J3MgZ2V0IGEgdGFibGUgb2YgdGhlbS4gUmV2aWV3IHRob3NlIEFGVEVSIEkndmUgZG9uZSB0aGUgY2xlYW51cHMgb2YgY291cnNlLiAKCmBgYHtyfQp4b3V0bGllcnMgPC0gaXFyICU+JQogIGFycmFuZ2UoZGVzYyh4SVFSKSkgJT4lCiAgc2xpY2UoMToxMCkKeW91dGxpZXJzIDwtIGlxciAlPiUKICBhcnJhbmdlKGRlc2MoeUlRUikpICU+JQogIHNsaWNlKDE6MTApCmBgYAoKTmV4dCwgY2hlY2sgdGhlIG1lZGlhbnMuCgpgYGB7cn0KaXFyICU+JSAKICBnYXRoZXIoYXhpcyxtZWQseG1lZDp5bWVkKSAlPiUKICBnZ3Bsb3QoYWVzKHg9bWVkLGZpbGw9YXhpcykpICsgZ2VvbV9oaXN0b2dyYW0oKSArIGZhY2V0X2dyaWQoYXhpc34uKSArIAogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDUwKSkKYGBgCgpTTyBJIG5lZWQgdG8gcmV2aWV3IHRob3NlIHRvby4gQWZ0ZXIgY2xlYW5pbmcgdXAvcmVtb3Zpbmcga2lkcy4KCmBgYHtyfQppcXIuZ2F0aGVyIDwtIGlxciAlPiUgZ2F0aGVyKGF4aXMsdmFsdWUseElRUjp5bWVkKQppcXIuaXFyIDwtIGZpbHRlcihpcXIuZ2F0aGVyLGF4aXM9PSJ4SVFSIiB8IGF4aXM9PSJ5SVFSIikKaXFyLm1lZCA8LSBmaWx0ZXIoaXFyLmdhdGhlcixheGlzPT0ieG1lZCIgfCBheGlzPT0ieW1lZCIpCgoKZ2dwbG90KGlxci5pcXIsYWVzKHg9bGFuZ3VhZ2UseT12YWx1ZSxmaWxsPWRpcmVjdGlvbikpICsgCiAgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBmYWNldF9ncmlkKC5+YXhpcykKYGBgCgpBbmQgdGhlIG1lZGlhbiB4IGFuZCB5IHBvc2l0aW9uICh0aGlzIGFzc3VtZXMgYWxsIGNhbGlicmF0aW9ucyBhcmUgY29ycmVjdCk6CgpgYGB7cn0KZ2dwbG90KGlxci5tZWQsYWVzKHg9bGFuZ3VhZ2UseT12YWx1ZSxmaWxsPWRpcmVjdGlvbikpICsgCiAgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBmYWNldF9ncmlkKC5+YXhpcykKYGBgCgpGaXJzdCwgZG9lcyByZXZlcnNhbCBhbmQgbGFuZ3VhZ2UgZXhwZXJpZW5jZSBoYXZlIGFuIGVmZmVjdCBvbiBYIElRUj8gV2UgaGF2ZSByYW5kb20gaW50ZXJjZXB0cyBmb3IgZWFjaCBwYXJ0aWNpcGFudCBhbmQgbWVkaWEsIGFuZCBhIHJhbmRvbSBzbG9wZSBhZGp1c3RtZW50IGZvciByZXZlcnNlZCBmb3IgZWFjaCBwYXJ0aWNpcGFudC4gCgpgYGB7cn0KeGlxci5yZXZlcnNhbCA8LSBsbWVyKHhJUVIgfiBkaXJlY3Rpb24gKiBsYW5ndWFnZSArIChkaXJlY3Rpb258cGFydGljaXBhbnQpICsgKDF8c3RvcnkpLCBkYXRhID0gaXFyKQpzdW1tYXJ5KHhpcXIucmV2ZXJzYWwpJGNvZWZmaWNpZW50cwpgYGAKClRoYXQncyBmaW5lLCB3ZSdyZSBub3QgZXhhY3RseSBwcmVkaWN0aW5nIGNoYW5nZXMgYWxvbmcgdGhlIHgtYXhpcy4gVGhlIHktYXhpcyBpcyB3aGF0IHdlIGFyZSByZWFsbHkgaW50ZXJlc3RlZCBpbiEgOikgCmBgYHtyfQp5aXFyLnJldmVyc2FsIDwtIGxtZXIoeUlRUiB+IGRpcmVjdGlvbiAqIGxhbmd1YWdlICsgKGRpcmVjdGlvbnxwYXJ0aWNpcGFudCkgKyAoMXxzdG9yeSksIGRhdGEgPSBpcXIpCnN1bW1hcnkoeWlxci5yZXZlcnNhbCkkY29lZmZpY2llbnRzCmBgYAoKCiMgVmlld2luZyBTcGFjZSBDaGFydHMKSSB3YW50IHRvIGxlYXJuIGhvdyB0byBtYWtlIHJlY3RhbmdsZSBwbG90cyBzbyBoZXJlIHdlIGdvLiBVc2luZyBlYWNoIHBhcnRpY2lwYW50J3MgZm91ciB4IGFuZCB5IG1lZGlhbnMgYW5kIDQgeCBhbmQgeSBJUVJzIChvbmUgc2V0IGZvciBlYWNoIHN0b3J5LCBmb3IgNCBzdG9yaWVzKS4gU28gSSBjYW4gZ2V0IHRoZSBsb2dpYyBhbmQgY29kZSBkb3duLiBMZXQncyBhc3N1bWUgYWxsIGNhbGlicmF0aW9ucyB3ZXJlIGNvcnJlY3QuIEhlcmUncyB0aGUgY2hhcnQgZm9yIHRoZSB3aG9sZSBtZWRpYSBzaXplIG9mIDE0NDB4MTA4MCAoYXMgcmVwb3J0ZWQgaW4gVG9iaWkpLiAKYGBge3J9CiMgSW4gdGhpcyBvcmRlciwgd2UnbGwgZ2V0IGEgZ3JhbmQgbWVkaWFuIGJ5IHRha2luZyBhIHBhcnRpY2lwYW50J3MgbWVkaWFuIGFjcm9zcyB0aGVpciA0IHN0b3JpZXMsIHRoYW4gdGhlIG1lZGlhbiBmb3IgZm9yd2FyZCBhbmQgcmV2ZXJzZSBhY3Jvc3MgYWxsIHBhcnRpY2lwYW50cy4gCm1lZGlhbnMgPC0gaXFyICU+JQogIGdyb3VwX2J5KHBhcnRpY2lwYW50LGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKHhJUVIgPSBtZWRpYW4oeElRUixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHlJUVIgPSBtZWRpYW4oeUlRUixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHhtZWQgPSBtZWRpYW4oeG1lZCxuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHltZWQgPSBtZWRpYW4oeW1lZCxuYS5ybT1UUlVFKSkgJT4lCiAgZ3JvdXBfYnkoZGlyZWN0aW9uKSAlPiUgCiAgc3VtbWFyaXNlKHhJUVIgPSBtZWRpYW4oeElRUixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHlJUVIgPSBtZWRpYW4oeUlRUixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHggPSBtZWRpYW4oeG1lZCxuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHkgPSBtZWRpYW4oeW1lZCxuYS5ybT1UUlVFKSkKCm1lZGlhbnMgPC0gbWVkaWFucyAlPiUKICBtdXRhdGUoeSA9IHkqLTEsCiAgICAgICAgIHhtaW4gPSB4LSh4SVFSLzIpLAogICAgICAgICB4bWF4ID0geCsoeElRUi8yKSwKICAgICAgICAgeW1pbiA9IHktKHlJUVIvMiksCiAgICAgICAgIHltYXggPSB5Kyh5SVFSLzIpKQoKaW1nIDwtIHJlYWRQTkcoImNpbmR5LnBuZyIpCmcgPC0gcmFzdGVyR3JvYihpbWcsIGludGVycG9sYXRlPVRSVUUsIHdpZHRoPXVuaXQoMSwibnBjIiksIGhlaWdodD11bml0KDEsIm5wYyIpKSAKCmdncGxvdChtZWRpYW5zLCBhZXMoZmlsbD1kaXJlY3Rpb24sY29sb3I9ZGlyZWN0aW9uKSkgKwogIGFubm90YXRpb25fY3VzdG9tKGcsIHhtaW49LUluZiwgeG1heD1JbmYsIHltaW49LUluZiwgeW1heD1JbmYpICsKICBnZW9tX3JlY3QoYWVzKHhtaW49eG1pbix5bWluPXltaW4seG1heD14bWF4LHltYXg9eW1heCksYWxwaGE9LjEpICsgCiAgdGhlbWVfbWluaW1hbCgpICsgeGxpbSgwLDE0NDApICsgeWxpbSgtMTA4MCwwKQoKCiMgZ2dwbG90KGlxci5nbG9iYWwsIGFlcyhmaWxsPWRpcmVjdGlvbixjb2xvcj1kaXJlY3Rpb24pKSArCiMgICBhbm5vdGF0aW9uX2N1c3RvbShnLCB4bWluPS1JbmYsIHhtYXg9SW5mLCB5bWluPS1JbmYsIHltYXg9SW5mKSArCiMgICBnZW9tX3JlY3QoYWVzKHhtaW49eG1pbix5bWluPXltaW4seG1heD14bWF4LHltYXg9eW1heCksYWxwaGE9LjEpICsgCiMgICB0aGVtZV9taW5pbWFsKCkgKyB4bGltKDAsMTQ0MCkgKyB5bGltKC0xMDgwLDApICsKIyAgIGdlb21faGxpbmUoeWludGVyY2VwdD0tMTA4MCs4ODUpICsKIyAgIGdlb21faGxpbmUoeWludGVyY2VwdD0tMTA4MCs1MjUpICsgCiMgICBhbm5vdGF0ZShnZW9tPSJ0ZXh0IiwgeCA9IDMwMCwgeSA9IC0xMDgwKzU1NSwgbGFiZWwgPSAidXBwZXIgc2hvdWxkZXIgcG9pbnQiKSArCiMgICBhbm5vdGF0ZShnZW9tPSJwb2ludCIsIHggPSA1MzUsIHkgPSAtMTA4MCs1MjUpICsgCiMgICBhbm5vdGF0ZShnZW9tPSJ0ZXh0IiwgeCA9IDUzNSwgeSA9IC0xMDgwKzkxMCwgbGFiZWwgPSAiaGVpZ2h0IGxpbmUiKSArIAojICAgYW5ub3RhdGUoZ2VvbT0icmVjdCIsIHhtaW4gPSA1MzUsIHhtYXggPSA1MzUrMzY1LCB5bWluID0gLTUyNS01NTEsIHltYXggPSAtMTA4MCs1MjUsIGZpbGw9Im1hcm9vbiIsIGNvbG9yPSJibGFjayIsIGFscGhhPTAuNSkgKyAKIyAgIGFubm90YXRlKGdlb209InRleHQiLCB4ID0gNzAwLCB5ID0gLTkwMCwgbGFiZWwgPSAidG9yc28iKQoKYGBgCgojIFZpZXdpbmcgU3BhY2UgQ2hhcnRzIGZvciBJbmRpdmlkdWFscwpOb3cgbGV0J3Mgc2VlIHRoZSB2YXJpYXRpb24gaW4gdmlld2luZyBzcGFjZXMgZm9yIGFsbCBvdXIgaW5kaXZpZHVhbHMuIFNob3VsZCBiZSBmdW4uCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MjZ9Cmlxci5pbmRpdmlkdWFscyA8LSBpcXIgJT4lCiAgcmVuYW1lKHggPSB4bWVkLAogICAgICAgICB5ID0geW1lZCkgJT4lCiAgbXV0YXRlKHkgPSB5Ki0xLAogICAgICAgICB4bWluID0geC0oeElRUi8yKSwKICAgICAgICAgeG1heCA9IHgrKHhJUVIvMiksCiAgICAgICAgIHltaW4gPSB5LSh5SVFSLzIpLAogICAgICAgICB5bWF4ID0geSsoeUlRUi8yKSkKCmdncGxvdChpcXIuaW5kaXZpZHVhbHMsIGFlcyhmaWxsPWRpcmVjdGlvbixjb2xvcj1kaXJlY3Rpb24pKSArCiAgYW5ub3RhdGlvbl9jdXN0b20oZywgeG1pbj0tSW5mLCB4bWF4PUluZiwgeW1pbj0tSW5mLCB5bWF4PUluZikgKwogIGdlb21fcmVjdChhZXMoeG1pbj14bWluLHltaW49eW1pbix4bWF4PXhtYXgseW1heD15bWF4KSxhbHBoYT0uMSkgKyAKICB0aGVtZV9taW5pbWFsKCkgKyB4bGltKDAsMTQ0MCkgKyB5bGltKC0xMDgwLDApICsgZmFjZXRfd3JhcCgiZGlyZWN0aW9uIikgKwogIGdndGl0bGUoIndpdGggSVFScyIpCmBgYAoKTm93IGxldCdzIG1ha2UgT3V0ZXIgTGltaXRzIGNoYXJ0cyB3aGljaCBpcyBJUVIgKy8tIDIgU0RzLiAgQnV0IEkgd2FudCB0byBjaGFuZ2UgdGhhdCBiZWNhdXNlIEkgZG9uJ3QgbGlrZSB0aGUgaWRlYSBvZiBtaXhpbmcgSVFScyBhbmQgU0RzLiAKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTI2fQojIHNkLmluZGl2aWR1YWxzIDwtIHNlbGVjdChzZC5pbmRpdmlkdWFscyxwYXJ0aWNpcGFudCxtZWRpYSx4c2QseXNkKQojIGlxcnNkLmluZGl2aWR1YWxzIDwtIGxlZnRfam9pbihpcXIuaW5kaXZpZHVhbHMsc2QuaW5kaXZpZHVhbHMsYnk9YygicGFydGljaXBhbnQiLCJtZWRpYSIpKSAlPiUKIyAgIG11dGF0ZSh4bWluID0geG1pbi0oMip4c2QpLAojICAgICAgICAgIHhtYXggPSB4bWF4KygyKnhzZCksCiMgICAgICAgICAgeW1pbiA9IHltaW4tKDIqeXNkKSwKIyAgICAgICAgICB5bWF4ID0geW1heCsoMip5c2QpKQojIAojIGdncGxvdChpcXJzZC5pbmRpdmlkdWFscywgYWVzKGZpbGw9ZGlyZWN0aW9uLGNvbG9yPWRpcmVjdGlvbikpICsKIyAgIGFubm90YXRpb25fY3VzdG9tKGcsIHhtaW49LUluZiwgeG1heD1JbmYsIHltaW49LUluZiwgeW1heD1JbmYpICsKIyAgIGdlb21fcmVjdChhZXMoeG1pbj14bWluLHltaW49eW1pbix4bWF4PXhtYXgseW1heD15bWF4KSxhbHBoYT0uMSkgKyAKIyAgIHRoZW1lX21pbmltYWwoKSArIHhsaW0oMCwxNDQwKSArIHlsaW0oLTEwODAsMCkgKyBmYWNldF93cmFwKCJkaXJlY3Rpb24iKSArCiMgICBnZ3RpdGxlKCJ3aXRoIFNEcyIpCmBgYAoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTI2fQojIGlxcnNkLmluZGl2aWR1YWxzIDwtIGlxcnNkLmluZGl2aWR1YWxzICU+JQojICAgZ3JvdXBfYnkoZGlyZWN0aW9uKSAlPiUKIyAgIGRwbHlyOjpzdW1tYXJpemUoeCA9IG1lYW4oeCxuYS5ybT1UUlVFKSwKIyAgICAgICAgICAgICB5ID0gbWVhbih5LG5hLnJtPVRSVUUpLAojICAgICAgICAgICAgIHhtaW4gPSBtZWFuKHhtaW4sbmEucm09VFJVRSksCiMgICAgICAgICAgICAgeW1pbiA9IG1lYW4oeW1pbixuYS5ybT1UUlVFKSwKIyAgICAgICAgICAgICB4bWF4ID0gbWVhbih4bWF4LG5hLnJtPVRSVUUpLAojICAgICAgICAgICAgIHltYXggPSBtZWFuKHltYXgsbmEucm09VFJVRSkpCiMgZ2dwbG90KGlxcnNkLmluZGl2aWR1YWxzLCBhZXMoZmlsbD1kaXJlY3Rpb24sY29sb3I9ZGlyZWN0aW9uKSkgKwojICAgYW5ub3RhdGlvbl9jdXN0b20oZywgeG1pbj0tSW5mLCB4bWF4PUluZiwgeW1pbj0tSW5mLCB5bWF4PUluZikgKwojICAgZ2VvbV9yZWN0KGFlcyh4bWluPXhtaW4seW1pbj15bWluLHhtYXg9eG1heCx5bWF4PXltYXgpLGFscGhhPS4xKSArIAojICAgdGhlbWVfbWluaW1hbCgpICsgeGxpbSgwLDE0NDApICsgeWxpbSgtMTA4MCwwKSArIGZhY2V0X3dyYXAoImRpcmVjdGlvbiIpICsKIyAgIGdndGl0bGUoIkF2ZXJhZ2Ugb2YgYWJvdmUgY2hhcnQgKHJhaW4ncyBvdXRlciBsaW1pdHMpIikKCmBgYAoKIyBXaXRoaW4tU3ViamVjdCBWYXJpYXRpb24KCkp1c3QgcmVhZCBbdGhpcyBnb29kIHBvc3RdKGh0dHBzOi8vbXZ1b3JyZS5naXRodWIuaW8vcG9zdC8yMDE3L3dpdGhpbi1zdWJqZWN0LXNjYXR0ZXIvKSBhYm91dCBwbG90dGluZyB3aXRoaW4tc3ViamVjdCB2YXJpYXRpb24gYW5kIHNhdyBpdCBjYW4gcmVhbGx5IGFwcGx5IHRvIHRoaXMgZGF0YXNldC4gU28gSSdtIGdvaW5nIHRvIHRyeSBvdXQgb25lIGV4YW1wbGUuIAoKV2Uga25vdyB0aGUgeSBtZWFucyBhcmVuJ3Qgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYWNyb3NzIGdyb3VwcyBidXQgdGhhdCdzIGJlZW4gaGFyZCB0byB2aXN1YWxpemUgb24gYSBwZXItc3ViamVjdCBiYXNpcyAob3IgZXZlbiBmcm9tIGFuIGVycm9yIGJhciBjaGFydCBzaW5jZSB0aGUgZXJyb3IgYmFycyBhcmUgc28gc21hbGwpLiBMZXQncyB2aXN1YWxpemUgdGhhdCEKCmBgYHtyfQojIEZpcnN0IGdldCB0aGUgbWVhbiBvZiBlYWNoIHRyaWFsLCBUSEVOIHRoZSBwYXJ0aWNpcGFudC1sZXZlbCBtZWFucwp3aXRoaW5fc3ViamVjdHMgPC0gZGF0YSAlPiUKICBncm91cF9ieShwYXJ0aWNpcGFudCwgYWdlZ3JvdXAsIGxhbmd1YWdlLCBkaXJlY3Rpb24sIHRyaWFsKSAlPiUKICBzdW1tYXJpc2UoeSA9IG1lYW4oeSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgY291bnQgPSBuKCkpICU+JQogIGdyb3VwX2J5KHBhcnRpY2lwYW50LCBhZ2Vncm91cCwgbGFuZ3VhZ2UsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHNlID0gc2QoeSwgbmEucm0gPSBUUlVFKS9zcXJ0KG4oKSksCiAgICAgICAgICAgIGNvdW50ID0gbigpKQoKIyBUaGVuIHNwcmVhZCBvdXQgbWVhbiBhbmQgU0UgY29sdW1ucyBieSBkaXJlY3Rpb24Kd2l0aGluX3N1YmplY3RzX21lYW5zIDwtIHdpdGhpbl9zdWJqZWN0cyAlPiUKICBzZWxlY3QoLXNlLCAtY291bnQpICU+JQogIHNwcmVhZChkaXJlY3Rpb24sIG1lYW4sIHNlcCA9ICJfIikKCndpdGhpbl9zdWJqZWN0c19zZSA8LSB3aXRoaW5fc3ViamVjdHMgJT4lCiAgc2VsZWN0KC1tZWFuLCAtY291bnQpICU+JQogIHNwcmVhZChkaXJlY3Rpb24sIHNlLCBzZXAgPSAiU0UiKQoKd2l0aGluX3N1YmplY3RzIDwtIGxlZnRfam9pbih3aXRoaW5fc3ViamVjdHNfbWVhbnMsIHdpdGhpbl9zdWJqZWN0c19zZSkKCiMgTm93IGxldCdzIHBsb3QganVzdCB0aGUgbWVhbnMKbGltcyA8LSBjKG1pbihkYXRhJHksIG5hLnJtID0gVCkrMTAwLCBtYXgoZGF0YSR5LCBuYS5ybSA9IFQpLTIwMCkKd2l0aGluX3N1YmplY3RzICU+JQogIGdncGxvdChhZXMoeCA9IGRpcmVjdGlvbl9mb3J3YXJkLCB5ID0gZGlyZWN0aW9uX3JldmVyc2VkLCBjb2xvciA9IGxhbmd1YWdlKSkgKwogIGdlb21fcG9pbnQoKSArIAogIGdlb21fYWJsaW5lKCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDEpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKCJmb3J3YXJkIiwgbGltaXRzID0gbGltcykgKwogIHNjYWxlX3lfY29udGludW91cygicmV2ZXJzZWQiLCBsaW1pdHMgPSBsaW1zKSArCiAgZ2d0aXRsZSgiWSBBeGlzIE1lYW5zIikgKwogIGZhY2V0X3dyYXAoImFnZWdyb3VwIikKCiMgbm93IHdpdGggZXJyb3IgYmFycwp3aXRoaW5fc3ViamVjdHMgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGlyZWN0aW9uX2ZvcndhcmQsIHkgPSBkaXJlY3Rpb25fcmV2ZXJzZWQsIGNvbG9yID0gbGFuZ3VhZ2UpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWRpcmVjdGlvbl9yZXZlcnNlZC1kaXJlY3Rpb25TRXJldmVyc2VkLCB5bWF4PWRpcmVjdGlvbl9yZXZlcnNlZCtkaXJlY3Rpb25TRXJldmVyc2VkKSkgKwogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluPWRpcmVjdGlvbl9mb3J3YXJkLWRpcmVjdGlvblNFZm9yd2FyZCwgeG1heD1kaXJlY3Rpb25fZm9yd2FyZCtkaXJlY3Rpb25TRWZvcndhcmQpKSArCiAgZ2VvbV9hYmxpbmUoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvID0gMSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoImZvcndhcmQiLCBsaW1pdHMgPSBjKDE0MCw0NjApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJyZXZlcnNlZCIsIGxpbWl0cyA9IGMoMTQwLDQ2MCkpICsKICBnZ3RpdGxlKCJZIEF4aXMgTWVhbnMiKSArCiAgZmFjZXRfd3JhcCgiYWdlZ3JvdXAiKQpgYGAKCg==